虚基类
解决多重继承中,一个公共基类可能在派生类中产生多个拷贝的现象。
如:有一个公共基类A,类B和类C都有类A派生,类D由类B和类C派生,则类D含有类A的两个拷贝,这不仅多占内存,还可能造成多个拷贝中的数据不一致。
#include <iostream> using namespace std; class A { public: int x; A(int a = 0) { x = a; } }; class B:public A { public: int y; B(int a = 0, int b = 0):A(b) { y = a; } void PB() { cout << "x=" << x << "y=" << y << '\n'; } }; class C:public A { public: int z; C(int a = 0, int b = 0):A(b) { z = a; } void PC() { cout << "x=" << x << "z=" << z << '\n'; } }; class D:public B, public C { public: int m; D(int a, int b, int d, int e, int f):B(a, b), C(d, e) { m = f; } void Print() { PB(); PC(); cout << "m=" << m << '\n'; } }; int main(void) { D d(100, 200, 300, 400, 500); d.Print(); return 0; }
x=200y=100
x=400z=300
m=500
D中包含类A的两个拷贝,从两个不同的x可以看出来。
在多重接继承中,如果希望公共基类在派生类中只有一个拷贝,可在定义派生类时将公共基类的类名前加上virtual即可。
#include <iostream> using namespace std; class A { public: int x; A(int a = 0) { x = a; } }; class B:virtual public A { //加virtual public: int y; B(int a = 0, int b = 0):A(b) { y = a; } void PB() { cout << "x=" << x << "y=" << y << '\n'; } }; class C:virtual public A { //加virtual public: int z; C(int a = 0, int b = 0):A(b) { z = a; } void PC() { cout << "x=" << x << "z=" << z << '\n'; } }; class D:public B, public C { public: int m; D(int a, int b, int d, int e, int f):B(a, b), C(d, e) { m = f; } void Print() { PB(); PC(); cout << "m=" << m << '\n'; } }; int main(void) { D d(100, 200, 300, 400, 500); d.Print(); return 0; }
x=0y=100
x=0z=300
m=500
解释:先调用虚基类的构造函数,然后调用非虚基类的构造函数。
类D的构造函数分别调用类B和类C的构造函数,由于类A在类D中只有一个拷贝,编译器无法确定是由类B还是类C的构造函数来调用类A的构造函数,这种情况下,编译器约定执行类B和类C的构造函数时都不调用虚基类A的构造函数,二是子类D的构造函数中直接调用虚基类A的默认构造函数,因此x为0.