菱形继承问题

文章前半部分引用:http://blog.csdn.net/icerlion/article/details/4409618

考虑这种情况:

class CA{};

class CB : public CA{};

class CC : public CA{};


这时我们需要一个CD类,它需要同时继承CB和CC。

问题就出现了。

如果我们这样写:

class CD : public CB, public CC{};

 

那么我们在构造一个CD类的时候,

其结果如下:

一个孙子有两个爷爷

 

即:一个CD类中有两个CA(它的超类的对象)

这样的情况是不合理的。此时会出现模糊调用的现象。

 

如何避免这种现象呢?

虚继承就有了用武之地。

 

我们需要改写CB和CC的继承方式。

class CB : public virtuel CA{};

class CC : public virtual CA{};

 

其他无需修改。此时我们构造一个CD类的时候,

其顺序如下:

开始构造CD类,

先构造一个超类CA,然后构造CB,

在构造CC(此时不会构造CC的父类CA)

这样一来,

CD类对象中包含的CB和CC将共享同一份CA对象。

 一个孙子就只有一个爷爷

这时就不会出现模糊调用的现象了。

 

这个就是C++臭名昭著的多继承。

在JAVA中根本不会出现这种情况,

如果必须使用菱形继承的时候务必使用虚拟继承。

如果你的项目中有太多的菱形继承,

你或许应该重新考核一下你的软件工程师。

--------------------------------------------------------------------------

例子:

fun.h

#ifndef FUN_H
#define FUN_H

class A
{
public:
    int a;
    A()
    {
        a=10;
    }
};

class B1:public A //没有使用虚继承
{
public:
    int b1;
    B1()
    {
        b1=1;
        a=11;
    }
};

class B2:public A //没有使用虚继承
{
public:
    int b2;
    B2()
    {
        b2=2;
        a=12;
    }
};

class C:public B1,public B2
{
public:
    int c;
    C()
    {
        c=3;
    }
};
#endif



// main.cpp

#include "fun.h"
#include <iostream>
using namespace std;

int main()
{
    C *pc=new C();
    cout<<pc->a<<endl;
    return 0;
}


编译不通过,提示A的数据成员a为模糊调用;

main.cpp: In function ‘int main()’:
main.cpp:25: error: request for member ‘a’ is ambiguous
fun.h:24: error: candidates are: int A::a
fun.h:24: error:                 int A::a
make: *** [all] 错误 1


当将fun.h中B1、B2改为虚拟继承A之后则可编译通过;

class B1:virtual public A

class B2:virtual public A


同时运行结果将为12,

root@debian6:/home/michael/cppProject/angleInheritance# make
g++ -c  main.cpp
g++ -o t main.o
rm *.o
root@debian6:/home/michael/cppProject/angleInheritance# ./t
12
结果12的原因是C类 构造函数C()会先调用虚基类A的构造函数A(),然后再调用自身父类构造函数B1(),B2(),调用顺序是根据“class C:public B1,public B2”从左向右依次进行。


若将C的继承顺序改为 class C:public B2,public B1”后,结果则为11

root@debian6:/home/michael/cppProject/angleInheritance# make
g++ -c  main.cpp
g++ -o t main.o
rm *.o
root@debian6:/home/michael/cppProject/angleInheritance# ./t
11







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值