[关闭]
@cxm-2016 2016-09-08T14:40:21.000000Z 字数 1151 阅读 1900

C++:虚基类

c++ no


假如B和C都继承自A而D继承自B和C,那么D对象中包含几个A对象呢?[1]

声明虚基类

虚基类使得从多个类派生出的对象只继承一个基类对象:

  1. class Singer : virtual public Worker{...};
  2. class Waiter : public virtual Worker{...};

然后可以将SingingWriter定义为:

  1. class SingingWriter : public Singer , public Waiter {...};

现在SingingWriter只包含一个Worker副本。

新的构造函数规则

使用虚基类时,需要对类构造函数采用一种新的方法。对于非需基类,我们只需要调用声明的基类的构造方法,不需要关心基类的基类的构造方法是什么样的:

  1. class A{
  2. public:
  3. A(int a){}
  4. };
  5. class B : A{
  6. public:
  7. B(int a,int b):A(a){}
  8. };
  9. class C : B{
  10. public:
  11. C(int a,int b,int c):B(a,b){}
  12. };

但是对于虚基类,我们就不能再采取这样的方式,而应该采用下面的方式

  1. SingingWaiter(const Worker & wk,int p,int v):
  2. Worker(wk),Waiter(wk,p),Singer(wk,v){}

也是就说,需要显式的调用被声明为虚基类的构造方法。

方法的二义性


对于单继承,方法调用会查找继承链中最近的重写方法。而在多继承系统中,每一个直接祖先都已共同基类中的方法。我们有如下几种方式解决二义性:

1,使用作用域解析符

  1. SingingWaiter sw;
  2. ...
  3. sw.Singer::show();

2,在子类重定义方法

对于使用作用域解析符的方法甚是繁杂。所以我们可以在子类中声明并定义一个自己的方法

  1. void SingingWaiter::show(){
  2. Singer::show();
  3. }

3,设置保护性继承

最后一种方式是将所有的数据组件都设置为保护的,而不是私有的,收方法的保护,外界不可以直接访问基类的方法,也就间接的防治了二义性的发生。

对于混合使用虚基类和非虚基类

假设A是B和C的虚基类,并作为D和E的非需基类,F类继承了B、C、D、E四个类。F对象中将会包含几个A对象。由于B、C是以虚基类方式继承了A所以这里只会产生一个A对象,但是对于D和E没有声明虚基类,就导致每个基类都会携带一个A对象。所以一共产生了3个A对象。


[1] Stephen Prata.C++ Primer Plus 6th.人民邮电出版社.2016.3 551~567
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注