33.C++-虚基类
虚基类
当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。
- 虚基类: 为了解决多重继承时,基类可能出现多次继承问题.
如下图所示:
如果未使用虚基类,那么D类会有两份类A的成员变量和函数,这在设计上来说,是多余的,因为D类只需要一个类A的成员变量和函数.
未使用虚基类-示例如下所示:
#include <iostream> using namespace std; class A { protected: int nv; public://外部接口 A(int n){ nv = n; cout << "Member of A" << endl; }//B0类的构造函数 void fun(){ cout << "fun of A" << endl; } }; class B : public A { int nv1; public: B(int a) :A(a){ cout << "Member of B" << endl; } }; class C : public A { int nv2; public: C(int a) :A(a){ cout << "Member of C" << endl; } }; class D :public B, public C { int nvd; public: D(int a) :B(a), C(a) { cout << "Member of D" << endl; // cout << nv << endl; // 将会报错,编译器不知道nv是B类还是C类的. cout << B::nv << endl; cout << C::nv << endl; B::fun(); C::fun(); } }; int main(void) { D d(1); return 0; }
打印如下所示:
为了解决继承下来的成员冗余问题,所以便有了虚基类,也就是虚继承.
虚继承就是在声明派生类的时候给基类加上virtual继承.如果有个派生类给基类加上了virtual继承,那么应当所有基类的直接派生类都应该声明virtual,否则也会出现多次继承问题
使用虚基类-示例如下所示:
#include <iostream> using namespace std; class A { protected: int nv; public://外部接口 A(int n){ nv = n; cout << "Member of A" << endl; }//B0类的构造函数 void fun(){ cout << "fun of B0" << endl; } }; class B : virtual public A {public: B(int a) :A(a){ cout << "Member of B" << endl; } }; class C : virtual public A {public: C(int a) :A(a){ cout << "Member of C" << endl; } }; class D :public B, public C {public: D(int a) : A(a), B(a), C(a) { cout << "Member of D" << endl; cout << nv << endl; fun(); } }; int main(void) { D d(1); return 0; }
打印如下所示:
此时的类D就只有一份类A的成员和函数了.需要注意的是:
- 如果虚基类的构造函数带有参数,那么需要在初始化列表对虚基类进行初始化,并且虚基类的其他派生类不会再对虚基类进行多次初始化.
比如我们将D类的构造函数改为:
D(int a) : A(200), B(1), C(1) { cout << "Member of D" << endl; cout << nv << endl; fun(); }
这时打印如下所示:
可以看到通过A(200)我们初始化nv为200后,并未被赋值回去
人间有真情,人间有真爱。