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/

C++虚继承作用的更多相关文章

  1. 虚基类&虚继承

    发现这个月准备竞赛完全没有更新哎... 改了下某华大一c++测试题...网上对虚继承讲的要么太繁琐要么不到位,自力更生 #include<iostream> #include<fst ...

  2. 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte

    #include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...

  3. c++ 虚继承

    虚继承(个人感觉用到的地方不多,项目中没有用到这个的) 最典型的例子就是iostream的继承方式 class istream : virtual public ios{...};//此处就是虚继承, ...

  4. 多重继承,虚继承,MI继承中虚继承中构造函数的调用情况

    先来测试一些普通的多重继承.其实这个是显而易见的. 测试代码: //测试多重继承中派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include < ...

  5. C++虚函数、虚继承

    http://blog.csdn.net/hackbuteer1/article/details/7883531 转载请标明出处,原文地址:http://blog.csdn.net/hackbutee ...

  6. virtual之虚函数,虚继承

    当类中包含虚函数时,则该类每个对象中在内存分配中除去数据外还包含了一个虚函数表指针(vfptr),指向虚函数表(vftable),虚函数表中存放了该类包含的虚函数的地址. 当子类通过虚继承的方式从父类 ...

  7. 虚函数&纯虚函数&抽象类&虚继承

    C++ 虚函数&纯虚函数&抽象类&接口&虚基类   1. 多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过 ...

  8. C++ 由虚基类 虚继承 虚函数 到 虚函数表

    //虚基类:一个类可以在一个类族中既被用作虚基类,也被用作非虚基类. class Base1{ public: Base1(){cout<<"Construct Base1!&q ...

  9. 2014 0416 word清楚项目黑点 输入矩阵 普通继承和虚继承 函数指针实现多态 强弱类型语言

    1.word 如何清除项目黑点 选中文字区域,选择开始->样式->全部清除 2.公式编辑器输入矩阵 先输入方括号,接着选择格式->中间对齐,然后点下面红色框里的东西,组后输入数据   ...

随机推荐

  1. tomcat 代码集

    Tomcat类是整个tomcat的起点,负责加载所有的配置信息以及把配置信息解析转换成tomcat组件对象. Context addWebapp(String contextPath, String ...

  2. 【转】IDA远程调试 The debugger could not attach to the selected process. irs_recv 等待的操作过时

    IDA连接android_server 选中进程点ok之后 连接不上报错 The debugger could not attach to the selected process. This can ...

  3. win7 PLSQL Developer 10/11/12 连接 Oracle 10/11/12 x64位数据库配置详解(与32位一样,只要注意对应Oracle Instant Client版本) tns 错误和 nls错误

    环境win7 x64 PLSQL Developer 10 与 11 Oracle Instant Client 10 与 12 参考http://blog.csdn.net/chen_zw/arti ...

  4. EasyCamera Android安卓移动视频监控单兵设备接入EasyDarwin开源流媒体云平台

    前言 随着Android系统的不断更新和发展,现在越来越多的硬件产品选择用安卓系统作为运行环境,电视机,机顶盒.门禁.行车记录仪.车载系统.单兵设备等等,Android系统底层还是Linux,但对上层 ...

  5. Linux就该这么学--命令集合6(打包压缩文件、文件查询搜索命令)

    1.tar命令用于对文件打包压缩或解压:(tar [选项] [文件]) 打包并压缩文件:tar -czvf 压缩包名.tar.gz 文件名 解压并展开压缩包:tar -xzvf 压缩包名.tar.gz ...

  6. selenium2 浏览器版本问题

    一.chrome浏览器 chrome浏览器与驱动版本对应关系 ----------ChromeDriver v2.26 (2016-12-09)---------- Supports Chrome v ...

  7. scroll或是其子类被添加进view时,界面自动上移

    开发中经常会遇到ViewController添加scroll或是其子类被添加进controller.view时,scroll会自动下移大概64像素 解决: self.edgesForExtendedL ...

  8. BestCoder3 1002 BestCoder Sequence(hdu 4908) 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4908 题目意思:给出 一个从1~N 的排列你和指定这个排列中的一个中位数m,从这个排列中找出长度为奇数 ...

  9. hdu-5773 The All-purpose Zero(LIS)

    题目链接: The All-purpose Zero Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (J ...

  10. hdu-5762 Teacher Bo(抽屉原理+暴力)

    题目链接: Teacher Bo Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...