文章前半部分引用: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;
}
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
class B1:virtual public A
class B2:virtual public A
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