完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1.多继承派生类有多个基类或者虚基类,同一个类不能多次作为某个派生类的直接基类,但可以作为一个派生类的间接基类;
class QUEUE: STACK, STACK{/…/}; //错误,出现两次 class Q: S {S d;/…/}; //正确:采用委托d代理的方式 1 2 2. 委托代理在多数情况下能够满足需要,但当对象成员和基类存在共同的基类时,就可能对同一个物理对象重复初始化(可能是危险的和不必要的); 3.两栖机车AmphibiousVehicle继承基类陆用机车LandVehicle,委托对象成员水上机WaterVehicle完成水上功能。两栖机车可能对同一个物理对Engine初始化(启动)两次。 class Engine{ /…/}; class LandVehicle: Engine{/…/}; class WaterVehicle: Engine{/…/}; class AmphibiousVehicle: LandVehicle{WaterVehicle wv; /…/}; 1 2 3 4 4.仅靠多继承仍然不能解决同一个物理对象初始化两次的问题 可以采用全局变量、静态数据成员,解决同一个物理对象初始化两次的问题,而如此解决相关析构问题则更使程序逻辑复杂化。 5.上述定义存在的问题:两栖机车要安装两个引擎Engine,可引入虚基类解决该问题。 6.虚基类 虚基类用virtual声明,把多个逻辑对象映射成同一个物理对象; 映射成的这个物理对象尽可能早的构造、尽可能晚的析构,构造和析构都只进行一次。若虚基类的构造函数都有参数,必须在派生类构造函数的初始化列表中列出虚基类构造参数。 同一颗派生树中的同名虚基类,共享同一个存储空间; 其构造和析构仅执行1次, 有虚基类的派生类构造函数不能使用consexpr定义; class Engine{ /…/ }; class LandVehicle: virtual public Engine{ /…/ }; class WaterVehicle: public virtual Engine{ /…/ }; class AmphibiousVehicle: LandVehicle, WaterVehicle { /…/ }; 1 2 3 4 继承关系 示例代码 class Engine { int power; public: Engine(int p) : power§ {} }; class LandVechicle : virtual public Engine { int speed; public: //如从AmphibiousVehicle调用LandVehicle,则不会在此调用Engine§ LandVechicle(int s, int p) : Engine§, speed(s) {} }; class WaterVechicle : virtual public Engine { int speed; public: //如从AmphibiousVehicle调用LandVehicle,则不会在此调用Engine§ WaterVechicle(int s, int p) : Engine§, speed(s) {} }; struct AmphibiousVechicle:LandVechicle,WaterVechicle{ AmphibiousVechicle(int s1,int s2,int p): //先构造虚基类再基类 WaterVechicle(s2,p),LandVechicle(s1,p),Engine§{} //整个派生树Engine§只1次 };//初始化顺序: Engine§, LandVehicle(s1, p), WaterVehicle(s2, p),而且进入两个 //LandVehicle, WaterVehicle 后,不再初始化这两个基类的基类Engine 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 7.派生类成员同名问题 当派生类成员和基类成员同名时,优先访问作用域小 的成员,即优先访问派生类的成员。当派生类数据成 员和派生类函数成员的参数同名时,在函数成员内优 先访问函数参数 示例代码 struct A{ int a, b, c, d; }; struct B{ int b, c; protected: int e; }; class C: public A, public B{ int a; public: int b; int f(int c); }; int C::f(int c){ int i=a; //访问C::a i=A::a; i=b+c+d; //访问C::b和参数c,A::d i=A::b+B::b; //访问基类成员 return A::c; } void main(void){ C x; int i=x.A::a; i=x.b; //访问C::b i=x.A::b+x.B::b; i=x.A::c; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 8.析构和构造 析构和构造的顺序相反,派生类对象的构造顺序 按自左至右、自下而上地构造倒派生树中所有虚基类; 按定义顺序构造派生类的所有直接基类; 按定义顺序构造(初始化)派生类的所有数据成员,包括对象成员、const成员和引用成员(少数编译按程序员指定顺序); 执行派生类自身的构造函数体; 示例代码1 #include using namespace std; struct A{ A(){ cout 《《 “A”;} }; struct B{ B(){ cout 《《 “B”;} }; struct C{ int a; int &b; const int c; C(char d):c(d),b(a) { a = d; cout 《《 d; } }; struct D{ D(){ cout 《《 “D”;} }; struct E:A,virtual B,C,virtual D{ A x,y; B z; E()?(),y(),C(‘C’){ cout 《《 “E”;} }; void test() { E e; } int main() { test(); system(“pause”); return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 输出 BDACAABE 1 分析 类E的派生图 依次构造e的虚基类B和D,B和D不再是派生类,执行B D构造输出函数B D; 依次构造e的基类A,C,A和C不再是派生类,C有const成员,这些成员初始化不产生输出,执行A C的构造函数输出A C; 依次构造e的对象成员x,y,z 输出A A B 最后输出e的构造函数E; 示例代码2 #include using namespace std; struct A { A() { cout 《《 ‘A’; } }; struct B { const A a; B( ) { cout 《《 ‘B’; } }; //对象成员a将作为新根 struct C: virtual A { C() { cout 《《 ‘C’; } }; struct D { D() { cout 《《 ‘D’; } }; struct E: A { E() { cout 《《 ‘E’; } }; struct F: B, virtual C { F() { cout 《《 ‘F’; } }; struct G: B { G() { cout 《《 ‘G’; } }; struct H: virtual C, virtual D { H() { cout 《《 ‘H’; } }; struct I: E, F, virtual G, H { E e; F f; I() { cout 《《 ‘I’; } }; int main() { I i; return 0; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 输出 ACABGDAEABFHAEACABFI 1 分析: 1)。 做出派生树 2)。 构造顺序 对象 i 有六棵派生树,树根分别为 I, a(A), a(A) , a(A) , e(E), 和f(F),同名虚基类 C 被合并; 自左向右,自上而下,依次构造 I 的虚基类 C, G,D。C 和 D 不是派生类,其数据成员也不用调用构造函数,故直接执行其构造函数;G 为派生类,构造G先构造B,构造B线构造对象成员 a;构造类 C输出 C,构造类G 输出 ABG,构造G输出 ABG,构造D 输出 D;综上, 构造I的虚基类输出 CABGD; 按照自左向右构造基类 E ,F, H 。E为派生类,先构造A,故构造E输出:AE;F为派生类,虚类C已经构造好,只需构造B,而B 需先构造 成员a,够构造F输出ABF;H虚基类已经全部构造完毕,只需输出 H;综上,构造 I 的基类输出 AEABFH; 按定义输出构造 I 的对象成员e,f,构造 e 输出AE,构造f 输出CABF;综上,构造对象成员e , f 的输出为AECABF; 最后 i 的构造体 I; 9.类的存储空间 多继承派生类包含多个基类的存储空间; 如果存在虚基类和同名基类,虚基类和同名基类空间是相互独立的。 如果派生类存在同名的虚基类,同一棵派生树的所有虚基类共享存储空间,虚基类通过偏移指向共享存储空间,该存储空间出现在所有直接基类之后; 如果基类或派生类存在虚函数,则在派生类存储空间中,包含一个单元存放虚函数入口地址表首地址; 派生类的存储空间不包括基类、虚基类和对象成员的静态数据成员。 |
|
|
|
只有小组成员才能发言,加入小组>>
930浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 10:00 , Processed in 0.779816 second(s), Total 80, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号