C++ - 虚拟继承的实现
2012-09-26 22:31
211 查看
1. 实现技术的挑战:
要找到一个足够有效的方法,将istream和ostream各自维护一个ios subobject,折叠成为一个由iostream维护的单一ios subobject,并且还可以保存base class和derived class的指针之间的多态指定操作。
2. 一种实现方法:
class如果内含一个或多个virtual base class subobject,像istream那样,将被分割为两部分:一个不变局部和一个共享局部。
不变局部中的数据,不管后继如何衍化,总是拥有固定的offset,所以这部分数据可以被直接存取。
至于共享局部,所表现的就是virtual base class subobject。这一部分数据,其位置会因为每次的派生操作而有变化,所以它们只可以被间接存取。
各家编译器实现技术之间的差异就在于间接存取的方法不同。主要有三种主流策略。
3. 布局策略之一:
先安排好derived class的不变部分,然后再建立其共享部分。在每一个derived class object中安插一些指针,每个指针指向一个virtual base class(这意味着,如果有多个虚基类,则需要多个指针分别依次指向)。要存取继承得来的virtual base class members,可以使用相关指针间接完成。
4. 布局策略一的缺点:
(1)每一个对象必须针对其每一个virtual base class背负一个额外的指针。
(2)由于虚拟继承串链的加长,导致间接存取层次的增加。
5. MetaWare编译器:
针对问题(2),通过拷贝操作获取所有嵌套的虚基类指针(nested virtual base class pointer),放到derived class object之中,这样就解决了“固定存取时间”的问题,不会出现间接存取层数增加的情况,但是付出了空间上的代价。
6. Microsoft编译器:
针对问题(1),引入虚基类表(virtual base class table),每一个class object如果有一个或多个虚基类(virtual base class),就会由编译器安插一个指针,指向虚基类表(virtual base class table),至于真正的virtual base class指针,当然是放在该表格中。
7. Bjarne解决方法:
针对问题(1),在virtual function table中放置virtual base class 的offset,而不是地址。
8. Sun编译器:
针对问题(1),将virtual base class offset和virtual function entries混杂在一起,virtual function table可经由正值或负值来索引,如果是正值,索引到virtual functions;如果是负值,索引到virtual base class offsets。
9. 优化:
经由一个非多态的class object来存取一个继承而来(即:派生类对象中的虚基类部分)的virtual base class的member,像这样:
Point3d origin;
origin._x; // _x为虚基类Point2d的成员
可以被优化为一个直接存取操作,就好像一个经由对象调用的virtual function调用操作,可以再编译时期被决议完成一样。在这次存取以及下次存取之间,对象的类型不会改变(因为前提是非多态),所以“virtual base class subobject的位置会变化”的问题在这种情况下就不再存在了。
10. 常用形式:
一般而言,virtual base class最有效的一种运用形式就是:一个抽象的virtual base class,没有任何data members。
要找到一个足够有效的方法,将istream和ostream各自维护一个ios subobject,折叠成为一个由iostream维护的单一ios subobject,并且还可以保存base class和derived class的指针之间的多态指定操作。
2. 一种实现方法:
class如果内含一个或多个virtual base class subobject,像istream那样,将被分割为两部分:一个不变局部和一个共享局部。
不变局部中的数据,不管后继如何衍化,总是拥有固定的offset,所以这部分数据可以被直接存取。
至于共享局部,所表现的就是virtual base class subobject。这一部分数据,其位置会因为每次的派生操作而有变化,所以它们只可以被间接存取。
各家编译器实现技术之间的差异就在于间接存取的方法不同。主要有三种主流策略。
3. 布局策略之一:
先安排好derived class的不变部分,然后再建立其共享部分。在每一个derived class object中安插一些指针,每个指针指向一个virtual base class(这意味着,如果有多个虚基类,则需要多个指针分别依次指向)。要存取继承得来的virtual base class members,可以使用相关指针间接完成。
4. 布局策略一的缺点:
(1)每一个对象必须针对其每一个virtual base class背负一个额外的指针。
(2)由于虚拟继承串链的加长,导致间接存取层次的增加。
5. MetaWare编译器:
针对问题(2),通过拷贝操作获取所有嵌套的虚基类指针(nested virtual base class pointer),放到derived class object之中,这样就解决了“固定存取时间”的问题,不会出现间接存取层数增加的情况,但是付出了空间上的代价。
6. Microsoft编译器:
针对问题(1),引入虚基类表(virtual base class table),每一个class object如果有一个或多个虚基类(virtual base class),就会由编译器安插一个指针,指向虚基类表(virtual base class table),至于真正的virtual base class指针,当然是放在该表格中。
7. Bjarne解决方法:
针对问题(1),在virtual function table中放置virtual base class 的offset,而不是地址。
8. Sun编译器:
针对问题(1),将virtual base class offset和virtual function entries混杂在一起,virtual function table可经由正值或负值来索引,如果是正值,索引到virtual functions;如果是负值,索引到virtual base class offsets。
9. 优化:
经由一个非多态的class object来存取一个继承而来(即:派生类对象中的虚基类部分)的virtual base class的member,像这样:
Point3d origin;
origin._x; // _x为虚基类Point2d的成员
可以被优化为一个直接存取操作,就好像一个经由对象调用的virtual function调用操作,可以再编译时期被决议完成一样。在这次存取以及下次存取之间,对象的类型不会改变(因为前提是非多态),所以“virtual base class subobject的位置会变化”的问题在这种情况下就不再存在了。
10. 常用形式:
一般而言,virtual base class最有效的一种运用形式就是:一个抽象的virtual base class,没有任何data members。
相关文章推荐
- C++多重继承 实现解耦,mvc分离
- c++ 接口继承和实现继承
- C++虚拟继承中_对象内存的分布_虚继承会多余分配虚表v-tab的指针vptr_图1-1清楚的描述了虚继承类对象内存的分布_转载淘宝共享数据平台
- C++虚函数实现&&单继承和多继承下的虚函数布局
- C语言模拟实现C++的继承与多态
- C++中虚拟继承总结
- 探讨C++实现一个不可被继承的类
- c++ 非虚拟继承可以正常使用,虚拟继承后执行的问题
- 关于C++中的虚拟继承的一些总结
- c语言模拟实现c++继承和多态
- 利用C++模板,代替虚函数实现类的静态多态性及动态继承
- C++中虚拟继承问题
- c++:继承相关的要点热点,以及菱形继承的底层实现
- C++私有继承实现has-a关系
- 【c++】实现一个不能被继承的类
- 【C++】区分接口继承和实现继承
- 用C++实现一个不能被继承的类
- 用C++实现一个不能被继承的类
- C++的虚拟继承机制
- C++中的虚继承,以及利用虚继承实现的sealed类