背景是:菱形继承
比如一个类C通过继承类A和类B,但是类A和类B又同时继承于公共基类N。示意图如下:
这种继承方式也存在数据的二义性,这里的二义性是由于他们间接都有相同的基类导致的。 这种菱形继承除了带来二义性之外,还会浪费内存空间。
类C中存在 两份的基类N,分别存在类A和类B中,如果数据多则严重浪费空间,也不利于维护, 我们引用基类N中的数据还需要通过域运算符进行区分。例如:
C data;
data.A::m_data1 = 10;
data.B::m_data1 = 10;
解决办法:使用虚继承
使得在派生类中只保留一份间接基类的成员。
在继承方式前面加上 virtual 关键字就是虚继承。
虚基类主要解决在多重继承时,基类可能被多次继承,虚基类主要提供一个基类给派生类.
虚表指针在整个继承关系中共享的,不共享的是指向虚基类的指针。
- //间接基类A
- class A{
- protected:
- int m_a;
- };
- //直接基类B
- class B: virtual public A{ //虚继承
- protected:
- int m_b;
- };
- //直接基类C
- class C: virtual public A{ //虚继承
- protected:
- int m_c;
- };
- //派生类D
- class D: public B, public C{
- public:
- void seta(int a){ m_a = a; } //正确
- void setb(int b){ m_b = b; } //正确
- void setc(int c){ m_c = c; } //正确
- void setd(int d){ m_d = d; } //正确
- private:
- int m_d;
- };
- int main(){
- D d;
- return 0;
- }
这样在派生类 D 中就只保留了一份成员变量 m_a,直接访问就不会再有歧义了。不然就会有2分成员变量m_a.