在《多继承》中讲过的例子中,由类A,类B1和类B2以及类C组成了类继承的层次结构......
在《多继承》中讲过的例子中,由类A,类B1和类B2以及类C组成了类继承的层次结构。在该结构中,类C的对象将包含两个类A的子对象。由于类A是派生类C两条继承路径上的一个公共基类,那么这个公共基类将在派生类的对象中产生多个基类子对象。如果要想使这个公共基类在派生类中只产生一个基类子对象,则必须将这个基类设定为虚基类。
虚基类的引入和说明 前面简单地介绍了要引进虚基类的原因。实际上,引进虚基类的真正目的是为了解决二义性问题。
虚基类说明格式如下:
virtual <继承方式><基类名>
其中,virtual是虚类的关键字。虚基类的说明是用在定义派生类时,写在派生类名的后面。例如:
class A { public: void f(); protected: int a; }; class B : virtual public A { protected: int b; }; class C : virtual public A { protected: int c: }; class D : public B, public C { public: int g(); private: int d; };
|
由于使用了虚基类,使得类A,类B,类C和类D之间关系用DAG图示法表示如下:
A{ f(), a }
/ \
B{b} C{c}
\ /
D{g(),d}
从该图中可见不同继承路径的虚基类子对象被合并成为一个对象。这便是虚基类的作用,这样将消除了合并之前可能出现的二义性。这时,在类D的对象中只存在一个类A的对象。因此,下面的引用都是正确的:
D n;
n.f(); file://对f()引用是正确的。
void D::g()
{
f(); file://对f()引用是正确的。
}
下面程序段是正确的。
D n;
A *pa;
pa = &n;
其中,pa是指向类A对象的指针,n是类D的一个对象,&n是n对象的地址。pa=&n是让pa指针指向类D的对象,这是正确的,并且也无二义性。