C++虚继承可以防止多重继承产生的二义性问题。

虚继承,就是在被继承的类前面加上virtual关键字,这时被继承的类称为虚基类,如下面代码中的base类。虚继承在多重继承的时可以防止二义性。

class base

class derived1 : virutal public base

class derived2 : virtual public base

class derived3 : public derived1, public derived2

以上的代码如果用到了base中的某个成员变量就不会产生二义性。和#progma once在头文件中的作用类似。请看下面的例子:

#include <iostream>

using namespace std;

class Parent

{

public:

int p;                                           // p将会被所有的子类继承,也将是二义性的根源

inline Parent()

{

p = 10;

}

};

class Child1 : public Parent

{

public:

int c1;

inline Child1()

{

p = 12;                           // p在子类Child1中被赋值为12

c1 = 12;

}

};

class Child2 : public Parent

{

public:

int c2;

inline Child2()

{

p = 13;                          // p在子类Child2中被赋值为13

c2 = 13;

}

};

class GrandChild : public Child1, public Child2

{

public:

int grandchild;

// p显然也存在于GrandChild中,但是到底是12,还是13呢?这就产生了二义性

inline GrandChild()

{

grandchild = 14;

}

};

int main(void)

{

GrandChild* pGC = new GrandChild();

cout << pGC->p << endl;

return 0;

}

上面程序是不能通过编译的,编译器输出的错误信息如下:

…: error C2385: 'GrandChild::p' is ambiguous

…: warning C4385: could be the 'p' in base 'Parent' of base 'Child1' of class 'GrandChild'

…: warning C4385: or the 'p' in base 'Parent' of base 'Child2' of class 'GrandChild'

正如编译器告诉我们的那样,GrandChild::p是模棱两可,它被Child1继承了即Child1中包含了一个Parent subobject,也被Child2继承了即Child2中也包含了一个Parent suboject,然后GrandChild又同时继承了Child1和Child2,根据“derived class中要保持base class的完整原样性原则”,因此GrandChild包含了两个ParentObject。所以当pGC->p时,编译器根本无法确定是调用Child1::p还是Child2::p,由此边产生了模棱两可的情形。怎么解决这样的问题呢?答案就是用虚继承或者叫虚基类的方式。

在上面的示例程序中做如下改动:

class Child1 : public Parent       ->     class Child1 : virtual public Parent

class Child2 : public Parent      ->      class Child2 : virtual public Parent

GrandChild的定义维持不变:

class GrandChild : public Child1, public Child2

做了上述改动后,即增加了两个virtual关键字,再编译就不会出现ambiguous之类的错误了。这是因为加上了virtual关键字后,就可以保证Parent suboject在GrandChild中只存在一份,从而消除了ambiguity。上面修改后的程序运行结果是13,这说明Child2类的那个p起了作用,如果GrandChild的定义写成:

class GrandChild : public Child2, public Child1

那么运行结果将是12。

上面的试验结果表面,在多重继承的时候,如果父类中有同名的成员变量(类似这篇文章中谈及的例子),为了防止二义性,一般要采用虚继承的方式,并且最右边的基类中的那个成员变量会出现在派生类对象中。

总结因果关系:多重继承—>二义性—>虚继承解决

转载自:http://xingyunbaijunwei.blog.163.com/blog/static/7653806720121188624918/

最新文章

  1. linux vi 命令大全
  2. infopath重复表格无法保存输入内容
  3. 第1章 重构,第一个案例(1):糟糕的statement函数设计
  4. Photoshop如何实现UI自动切图?
  5. Spring中配置数据源的4种形式(转)
  6. -XX:+PrintGCTimeStamps 打印CG发生的时间戳
  7. spark_updateStateByKey
  8. Poj 1904 King&#39;s Quest 强连通分量
  9. 不逃离WIndows,Asp.Net就只能写写进销存管理系统
  10. [iOS UI进阶 - 2.0] 彩票Demo v1.0
  11. springxml配置构造函数入参
  12. 关于解决方案和web文件夹放在同一目录路径错误的问题
  13. SpringDataRedis事务处理
  14. jvm栈和堆详解
  15. Unity 游戏框架搭建 (二十) 更安全的对象池
  16. JSON Patch
  17. C&amp;C++ Calling Convention
  18. 解决Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/cqupt/paging/dao/User.xml
  19. Git工具使用
  20. Spring boot设置文件上传大小限制

热门文章

  1. Java中Class.forName()的作用(转载)
  2. EasyDarwin开源流媒体server将select改为epoll的方法
  3. SAP-ABAP系列 第二篇SAP ABAP开发基础
  4. compute the su procedure time with python
  5. c#生成试卷。。。
  6. CSDN第一期总结之三:Thread的问题(转)
  7. 20170316 ABAP注意点
  8. iOS 判定string是不是中文字符
  9. jquery特效(8)—倒计时
  10. GDP与股市市值