1.多重继承的概念:一个类有两个或者更多个基类
形式为 class <类名>:<访问属性> class <类名>,<访问属性> class <类名>
如 class A:public class B,public class C
上面的定义中,如果B和C都有print函数,这时A类的对象调用print函数,将会发生二义性,这是多重继承存在的缺陷,避免这种二义性,可以用域访问符::,如A类的对象a访问B类中的print函数,可以用a.B::print().
2.在多重继承下,一个基类可以再派生层次中出现多次,比如下面的继承结构
A类派生 B和C类,D类继承自B类和C 类。
D类的对象沿着A—B—D的方向有了A的一份副本,沿着A—C—D的方向有了第二个副本,这时在调用某些成员时难免会出现二义性,C++引入了虚继承机制来解决这个问题,将A类声明为B类和C类的虚基类,这样D类的对象只会含有A类的一个副本。
虚基类的声明要加上virtual关键字,方式如下:
Class B:virtual pubic A
Class C:virtual public A
在回到刚刚讲到的二义性问题,如果A类有成员x,那么D类的对象在访问成员x时,可以完全消除二义性吗?并不能完全消除。这里要分三种情况
(1)如果x仅仅在A类中出现,调用成员x将没有二义性
(2)如果x成员在A类中和B类中同时出现,D类对象调用的将是B类的成员x,这说明派生类的实例优先级高于共享虚基类的实例
(3)如果x成员在B类中和C类中同时出现,D类对象调用成员x时,将会出现二义性
下面是说明的代码:
# include <iostream> using namespace std; class Base { public: Base(int t):x(t){} void print(){cout<<x<<endl;} int get(){return x;} int x; }; class Der1:virtual public Base { public: Der1(int t):Base(t){} void print(){cout <<x<<endl;} int addx(){return ++x;} }; class Der2:virtual public Base { public: Der2(int t):Base(t){} int addx(){return ++x;} }; class Der3:public Der1,public Der2 { public: Der3(int t):Base(t),Der1(t),Der2(t){} //虚继承中,底层派生类初始化所有基类 }; int main() { Der3 p(4); //定义派生类的对象 p.print(); //print 出现在基类Base和Der1中,会选择调用Der1的版本 cout<<p.get()<<endl;//get()仅仅出现杂虚基类Base中,不会引起二义性 //cout<<p.addx()<<endl;// addx() 出现在基类Der1和Der2中,会引起二义性 cin.get(); return 0; }
3.虚继承中的构造顺序和析构顺序
在上面四个类ABCD的继承层次中,构造函数的调用顺序为A—B—C—D ,析构函数的调用顺序刚好相反。
在更复杂的继承结构中,虚基类和普通基类同时出现,虚基类的调用优先级高于非虚基类,不管虚基类位于什么继承层次,虚基类的构造函数在非虚基类之前调用。
原文:http://blog.csdn.net/u011608357/article/details/18840701