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++:多继承中的二义性问题

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

C++中多重继承的二义性及解决办法

转载自:http://www.cnblogs.com/lintong/archive/2012/07/28/2613002.html 1. 什么是多重继承的二义性 ...
  • liguohanhaha
  • liguohanhaha
  • 2016年04月27日 10:31
  • 1389

多重继承的二义性以及解决方法

//多重继承的二义性以及解决方法 //学习目的:了解类的继承原理及多重继承二义性的解决方法。 /* //本程序代码来源《MFC权威剖析》p68 */ ////////////////////...
  • windows_nt
  • windows_nt
  • 2013年02月27日 09:31
  • 5332

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

虚继承,就是在被继承的类前面加上virtual关键字,这时被继承的类称为虚基类,如下面代码中的base类。虚继承在多重继承的时可以防止二义性。     class base;     clas...
  • Lostyears
  • Lostyears
  • 2012年03月08日 19:21
  • 377

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

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

通过菱形继承剖析虚继承解决二义性和数据冗余问题

什么是菱形继承?     假设有一个类A,它有两个子类,分别为类B和类C,再有一个类D又继承了B类和C类;如图: 类似于这种,有子类对象包含多份父类对象的继承模型称为菱形继承。 上述菱形继承体系中...
  • L__xing
  • L__xing
  • 2017年11月05日 17:39
  • 182

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

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

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

1.共同基类派生产生的二义性及解决办法
  • wu_123_456
  • wu_123_456
  • 2014年04月24日 16:51
  • 574

c++语言中易引起二义性问题 2 之类的继承问题以及成员数据覆盖问题不如忽视!

派生类 继承了多个相同的成员函数或成员数据! 请看下面的代码: #include using namespace std; class h {  public:        ...
  • u010672206
  • u010672206
  • 2013年06月10日 12:24
  • 571

C++多继承的二义性

多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。     多继承下派生类的定义格式如下:     class :,,… ...
  • whui890911
  • whui890911
  • 2013年05月18日 15:24
  • 738
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++中虚继承防止二义性
举报原因:
原因补充:

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