虚基类:有virtual关键字的类。
class base
class derived1 : virutal public base
class derived2 : virtual public base
class derived3 : public derived1, public derived2
如果用到了base中的某个成员变量就不会产生二义性。和#progmaonce在头文件中的作用类似。
#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;
}
上面程序是不能通过编译的,derived class中要保持base class的完整原样性原则。
在上面的示例程序中做如下改动:
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关键字后,就可以保证Parentsuboject在GrandChild中只存在一份。上面修改后的程序运行结果是13,这说明Child2类的那个p起了作用,如果GrandChild的定义写成: class GrandChild : public Child2, public Child1那么运行结果将是12。
在多重继承的时候,如果父类中有同名的成员变量,为了防止二义性,一般要采用虚继承的方式,并且最右边的基类中的那个成员变量会出现在派生类对象中。