C++中虚继承防止二义性

转载 2012年03月28日 23:09:26

虚继承,就是在被继承的类前面加上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中被赋值为

               c1 = 12;

      }

};

 

class Child2 : public Parent

{

public:

      int c2;

 

      inline Child2()

      {

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

               c2 = 13;

      }

};

 

class GrandChild : public Child1, public Child2

{

public:

      int grandchild;

 

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

      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又同时继承了Child1Child2,根据“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 subojectGrandChild中只存在一份,从而消除了ambiguity。上面修改后的程序运行结果是13,这说明Child2类的那个p起了作用,如果GrandChild的定义写成:

class GrandChild : public Child2, public Child1

那么运行结果将是12

 

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


相关文章推荐

C++中虚继承防止二义性

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

什么叫虚继承(虚拟继承)?如何消除继承中的二义性?

乍听虚继承,吓倒很多人!! 或许很多人会认为这和虚函数有关,其实,几乎没有任何关系。它的出现,是为了克服继承中一个非常棘手的问题,也就是臭名昭著的菱形继承(二义性)问题。 二义性,也就是说,假如我...

C++虚函数分析[1]--同名函数继承二义性问题

概念多重继承,最常见的问题就是继承的成员同名而产生的二义性(ambiguous)问题。 会产生同名覆盖的问题,即最终访问的就是派生类的成员(函数完全相同,否则为函数重载)。#include usi...

C/C++日常学习总结(第四篇)共同基类产生的二义性和继承与组合的区别

1.共同基类派生产生的二义性及解决办法

C++多继承的二义性

多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。     多继承下派生类的定义格式如下:     class :,,… ...

C++课件 类、流、虚继承

  • 2010年12月20日 14:24
  • 11.72MB
  • 下载

C++:多继承中的二义性问题

在派生类中对基类成员的访问应该是唯一的.但是,在多继承情况下,可能造成对基类中某个成员的访问出现了不一致的 情况,这时就称对基类成员的访问产生了二义性. 原因之一:    派生类在访问基类成员函数...

C++语言笔记系列之十六——赋值兼容规则&多继承的二义性

1.赋值兼容规则 (1)派生类对象可以给基类对象赋值,这种情况下派生类对象将从基类继承的成员的值赋值给一个基类对象;但是不允许将一个基类的对象赋值给一个派生类。 (2)可以将派生类对象的地址赋给基类指...

C/C++日常学习总结(第三篇)不能重载的运算符和不同基类继承产生的二义性

1.作用域

从多重继承中的二义性 到 虚基类(摘抄自谭浩强c++)

一个多重继承的程序 #include using namespace std; class Teacher { public: Teacher(string nam,int a,string...
  • wsyxhwj
  • wsyxhwj
  • 2016年05月11日 16:15
  • 379
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++中虚继承防止二义性
举报原因:
原因补充:

(最多只允许输入30个字)