c++之虚基类

1.虚基类

在多继承关系中,如果一个派生类的从两个父类那里继承过来,并且这两个父类又恰恰是从一个基类那里继承而来【菱形继承问题】。那这样就麻烦了,因为你可能继承了两份一样的成员!这不仅多占用内存,而且还出现了所谓二义性问题

#include <iostream>
using namespace std;

class Grandfather
{
public:
    int key;
public:
};

class Father1:public Grandfather
{
};
class Father2:public Grandfather
{
};
class Grandson:public Father1,public Father2
{
};
int main() { Grandson A; //A.key=9; return 0; }

定义的四个类都很空,重点看继承关系即可。即Grandson类继承两个father类,会有两个key成员,这个时候如果试图使用这个key,注意已经声明为public类型,在主函数中试图赋值时候,会有“不唯一、模棱两可”的错误提示,即所谓的二义性问题发生

因此,在多重继承中,若希望公共基类在派生类中只有一个拷贝,可将该基类说明为虚基类。即在定义派生类时,在继承的公共基类类名前加上关键字 virtual。那么这个时候,派生类和基类就只维护一份一个基类对象。避免多次拷贝,出现歧义。

class Father1:virtual public Grandfather

class Father2:virtual public Grandfather

2.注意事项

如果派生类继承了多个基类,基类中有虚基类和非虚基类,那么在创建该派生类的对象时,先调用虚基类的构造函数,然后调用非虚基类的构造函数,最后调用派生类的构造函数。若虚基类有多个,则虚基类构造函数的调用顺序取决于它们继承时的说明顺序。

class A {

public:
    int x;
    void SetX(int a) { x = a; }
    A(int a = 0) { x = a; cout << "调用A构造函数" << endl;
    }
    void PA() { cout << "PA" <<x<< endl; }
};
class B :virtual public A {
public:
    int y;
    void SetY(int a) { y = a; }
    B(int a = 0, int b = 0):A(a) { y = b; cout << "调用B构造函数" << endl;
    }
    void PB() { cout << "PB" << "x="<<x<<"y="<<y<<endl; }
};
class C :virtual public A {
public:
    int z;
    void SetZ(int a) { z= a; }
    C(int a = 0, int b = 0) :A(a) { z = b; cout << "调用C构造函数" << endl; }
    void PC() { cout << "PC" <<"x="<<x<<"z="<<z<<endl; }
};
class D :public B, C {
    int m;
public:
    D(int a = 0, int b = 0, int c = 0,int d=0,int e=0):B(a,b),C(c,d) {  m = e; cout << "调用D构造函数" << endl;
    }
    void PD() {  PB();PC();cout<< "x=" << x << "y=" << y << "z=" << z<< endl;
    }
};

int main()
{
D d1(1,2,3,4,5);
d1.PD();
return 0;
}

所以,当基类设置为虚基类时,只拷贝一次虚基类。
但是,为何基类的数据成员x数值为0???
因为类D的构造函数调用了B和C的构造函数,类B和C又调用了类A的构造函数,但是因为由于虚基类在D中只有一个拷贝,编译器无法确定是由B还是C的构造函数调用A的构造函数,所以,编译器约定,执行B和C的构造函数时不调用虚基类A的构造函数,而在类D的构造函数中直接调用A的默认的构造函数。
如果派生类继承了多个基类,基类中有虚基类和非虚基类,那么在创建该派生类的对象时,先调用虚基类的构造函数,然后调用非虚基类的构造函数,最后调用派生类的构造函数。若虚基类有多个,则虚基类构造函数的调用顺序取决于它们继承时的说明顺序。

posted on 2023-03-09 18:05  斗战胜佛美猴王  阅读(117)  评论(0编辑  收藏  举报