1. 多重继承时的二义性
当使用多重继承时,如果多个父类都定义了相同名字的变量,则会出现二义性。解决方法:使用 :: 声明作用域
#include <iostream> using namespace std; class A { public: int x; int y; A() { cout << "A 默认构造函数" << endl; x = 1; y = 1; } }; class B { public: int x; int y; B() { cout << "B 默认构造函数" << endl; x = 2; y = 2; } }; class C:public A, public B { public: int x; int y; C() { cout << "C 默认构造函数" << endl; x = 3; y = 3; } }; int main() { C c; cout << c.x << endl; // 3 cout << c.A::x << endl; // 1 cout << c.B::x << endl; // 2 cout << c.C::x << endl; // 3 return 0; }
2. 多个基类副本
如图所示的继承关系,如果不用虚继承会产生多个基类副本
#include <iostream> using namespace std; class A { public: int x; int y; A() { cout << "A 默认构造函数" << endl; x = 1; y = 1; } }; class B:public A { public: B() { cout << "B 默认构造函数" << endl; } }; class C:public A { public: C() { cout << "C 默认构造函数" << endl; } }; class D:public B, public C { public: D() { cout << "D 默认构造函数" << endl; } }; int main() { D d; //d.x = 20; 报错 x 不明确 //d.A::x = 20; 报错,基类A不明确 d.B::x = 20; cout << d.B::x << endl; // 20 cout << d.C::x << endl; // 1 未改变 return 0; }
注意,A的构造函数使用了两次。B和C构造函数的顺序与继承时声明的顺序相同。
3. 虚继承
在继承时使用virtual,这样就不会产生基类副本了
#include <iostream> using namespace std; class A { public: int x; int y; A() { cout << "A 默认构造函数" << endl; x = 1; y = 1; } }; class B: virtual public A { public: B() { cout << "B 默认构造函数" << endl; } }; class C:virtual public A { public: C() { cout << "C 默认构造函数" << endl; } }; class D:public B, public C { public: D() { cout << "D 默认构造函数" << endl; } }; int main() { D d; d.B::x = 20; cout << d.x << endl; // 20 cout << d.A::x << endl; // 20 cout << d.B::x << endl; // 20 cout << d.C::x << endl; // 20 return 0; }
注意:A的构造函数只使用了一次。且所有的x都统一了,没有二义性。