有时单继承是不够解决问题的,需要多重继承,即一个派生类从多个基类派生而来,
但在派生列表中每个类只允许出现一次。
派生类的构造函数在初始化列表中调用最直接的一个或多个基类的构造函数(定义了自己的考构和赋值运算符也请遵循)。创立对象时众基类的建造顺序按照派生列表中的顺序进行。析构则是严格相反的顺序。
每个基类型的指针或引用(实际对象为派生类对象)都可以触发动态绑定,同理delete该指针时,会触发层层析构(别忘了基类一定要的virtual destructor)。
派生类中的名字解析按照每一个基类的分支(subtree)分别进行查找,如果出现2义性则报错。
- class a{
- public:
- void print(){cout<<"in a\n";}
- };
- class a2{
- public:
- void print(int ){cout<<"in a2\n";}
- };
- class c:public a,public a2{
- public:
- int cc;
- };
- int main()
- {
- c obj;
- obj.print();
- cout<<"end in main\n";
- return 0;
- }
c派生自a和a2,各自有一个print,
即使参数不同,c没有定义自己的print,编译报错:
test.cpp: In function `int main()':
test.cpp:31: request for member `print' is ambiguous
test.cpp:10: candidates are: void a::print()
test.cpp:20: void a2::print(int)
如果将其中一个改为private也不行,会多出2行编译结果:
test.cpp:10: `void a::print()' is private
test.cpp:34: within this context
改为下面这样调用就可以了,obj.a2::print(); 注意不能是obj.a2.print(); 会提示
test.cpp:31: invalid use of type decl `class a2' as expression
- int main()
- {
- c obj;
- obj.a2::print();
-
- cout<<"end in main\n";
- return 0;
- }
当多重继承中的基类中有2个或更多来自(直接或间接)于同一个基类b时,那么最终派生类中关于这个基类b的副本就不只一份,浪费了存储空间。为了解决这种情况,可以在派生列表中加入virtual关键字,称之为虚继承。则最终派生类中只会拥有基类b的一份副本。
class b: public virtual a{...};
class c: public virtual a{...};
class d: public b,public c{...};//d中a的副本只有一个。
此种虚基类的初始化必须由最终创建对象的派生类(most derived class)负责初始化,即d的构造函数在初始化列表首先要调用a的构造函数,然后才是b,c的。b,c构造函数中关于a的调用会被忽略。
派生类有着多个虚基类时,按照派生列表中的顺序进行搜索,找到一个虚基类,进行创建,再找下一个。全部的虚基类初始化完毕后,再按照派生列表中顺序进行非虚基类对象的初始化创建。
阅读(394) | 评论(0) | 转发(0) |