C++ 多重继承

来源:互联网 发布:域名收费标准 编辑:程序博客网 时间:2024/06/05 17:06

1.多重继承的概念:一个类有两个或者更多个基类

形式为  class  <类名><访问属性> class <类名><访问属性> class <类名>

class A:public class B,public class C   

上面的定义中,如果BC都有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 ,析构函数的调用顺序刚好相反。

在更复杂的继承结构中,虚基类和普通基类同时出现,虚基类的调用优先级高于非虚基类,不管虚基类位于什么继承层次,虚基类的构造函数在非虚基类之前调用。


1 0