C++类所占内存大小计算
2016-04-08 10:14
375 查看
C++中虚拟继承的概念
为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。
class派生类名:virtual继承方式基类名
virtual是关键字,声明该基类为派生类的虚基类。
在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。
声明了虚基类之后,虚基类在进一步派生过程中始终和派生类一起,维护同一个基类子对象的拷贝。
C++虚拟继承
◇概念:
C++使用虚拟继承(VirtualInheritance),解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。
◇解决问题:
解决了二义性问题,也节省了内存,避免了数据不一致的问题。
◇同义词:
虚基类(把一个动词当成一个名词而已)
当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明为虚基类。
◇语法:
class派生类:virtual基类1,virtual基类2,...,virtual基类n
{
...//派生类成员声明
};
◇执行顺序
首先执行虚基类的构造函数,多个虚基类的构造函数按照被继承的顺序构造;
执行基类的构造函数,多个基类的构造函数按照被继承的顺序构造;
执行成员对象的构造函数,多个成员对象的构造函数按照申明的顺序构造;
执行派生类自己的构造函数;
析构以与构造相反的顺序执行;
mark
从虚基类直接或间接派生的派生类中的构造函数的成员初始化列表中都要列出对虚基类构造函数的调用。但只有用于建立对象的最派生类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类的构造函数的调用在执行中被忽略,从而保证对虚基类子对象只初始化一次。
在一个成员初始化列表中同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。
◇因果:
多重继承->二义性->虚拟继承解决
◇二义性:
1://-----------------------------------------------------
2://名称:blog_virtual_inherit.cpp
3://说明:C++虚拟继承学习演示
4://环境:VS2005
5://blog:pppboy.blog.163.com
6://----------------------------------------------------
7:#include"stdafx.h"
8:#include<iostream>
9:usingnamespacestd;
10:
11://Base
12:classBase
13:{
14:public:
15:Base(){cout<<"Basecalled..."<<endl;}
16:voidprint(){cout<<"Baseprint..."<<endl;}
17:private:
18:};
19:
20://Sub
21:classSub//定义一个类Sub
22:{
23:public:
24:Sub(){cout<<"Subcalled..."<<endl;}
25:voidprint(){cout<<"Subprint..."<<endl;}
26:private:
27:};
28:
29://Child
30:classChild:publicBase,publicSub//定义一个类Child分别继承自Base,Sub
31:{
32:public:
33:Child(){cout<<"Childcalled..."<<endl;}
34:private:
35:};
36:
37:intmain(intargc,char*argv[])
38:{
39:Childc;
40:
41://不能这样使用,会产生二意性,VC下errorC2385
42://c.print();
43:
44://只能这样使用
45:c.Base::print();
46:c.Sub::print();
47:
48:system("pause");
49:return0;
50:}
◇多重继承:
1://-----------------------------------------------------
2://名称:blog_virtual_inherit.cpp
3://说明:C++虚拟继承学习演示
4://环境:VS2005
5://blog:pppboy.blog.163.com
6://----------------------------------------------------
7:#include"stdafx.h"
8:#include<iostream>
9:usingnamespacestd;
10:
11:intgFlag=0;
12:
13:classBase
14:{
15:public:
16:Base(){cout<<"Basecalled:"<<gFlag++<<endl;}
17:voidprint(){cout<<"Baseprint"<<endl;}
18:};
19:
20:classMid1:publicBase
21:{
22:public:
23:Mid1(){cout<<"Mid1called"<<endl;}
24:private:
25:};
26:
27:classMid2:publicBase
28:{
29:public:
30:Mid2(){cout<<"Mid2called"<<endl;}
31:};
32:
33:classChild:publicMid1,publicMid2
34:{
35:public:
36:Child(){cout<<"Childcalled"<<endl;}
37:};
38:
39:intmain(intargc,char*argv[])
40:{
41:Childd;
42:
43://不能这样使用,会产生二意性
//d.print();
45:
46://只能这样使用
47:d.Mid1::print();
48:d.Mid2::print();
49:
50:system("pause");
51:return0;
52:}
53:
//output
Basecalled:0
Mid1called
Basecalled:1
Mid2called
Childcalled
Baseprint
Baseprint
◇虚拟继承
在派生类继承基类时,加上一个virtual关键词则为虚拟继承
1://-----------------------------------------------------
2://名称:blog_virtual_inherit.cpp
3://说明:C++虚拟继承学习演示
4://环境:VS2005
5://blog:pppboy.blog.163.com
6://----------------------------------------------------
7:#include"stdafx.h"
8:#include<iostream>
9:usingnamespacestd;
10:
11:intgFlag=0;
12:
13:classBase
14:{
15:public:
16:Base(){cout<<"Basecalled:"<<gFlag++<<endl;}
17:voidprint(){cout<<"Baseprint"<<endl;}
18:};
19:
20:classMid1:virtualpublicBase
21:{
22:public:
23:Mid1(){cout<<"Mid1called"<<endl;}
24:private:
25:};
26:
27:classMid2:virtualpublicBase
28:{
29:public:
30:Mid2(){cout<<"Mid2called"<<endl;}
31:};
32:
33:classChild:publicMid1,publicMid2
34:{
35:public:
36:Child(){cout<<"Childcalled"<<endl;}
37:};
38:
39:intmain(intargc,char*argv[])
40:{
41:Childd;
42:
43://这里可以这样使用
44:d.print();
45:
46://也可以这样使用
47:d.Mid1::print();
48:d.Mid2::print();
49:
50:system("pause");
51:return0;
52:}
53:
//output
1:Basecalled:0
2:Mid1called
3:Mid2called
4:Childcalled
5:Baseprint
6:Baseprint
7:Baseprint
8:请按任意键继续...
◇通过输出的比较
1.在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。
2.声明了虚基类之后,虚基类在进一步派生过程中始终和派生类一起,维护同一个基类子对象的拷贝。
3.观察类构造函数的构造顺序,拷贝也只有一份。
◇与虚函数关系
虚拟继承与虚函数有一定相似的地方,但他们之间是绝对没有任何联系的。
再想一次:虚拟继承,虚基类,虚函数。
相关文章推荐
- C++第二次实验作业
- c++实验2 正整数类
- C语言宏接收函数及其参数
- 01. C++经验积累related to vtk
- C语言中,数组名作为参数传递给函数时,退化为指针
- c++中类没有数据成员时,类对象的大小
- (AC自动机 + 矩阵加速)
- 安装LR11 时,安装Microsoft Visual c++2005 sp1运行时组件,就会提示命令行选项语法错误,键入“命令/?”可获取帮肋信息
- C++实现——序列的下一个字典序
- c++ rand方法解析
- c/c++库函数整理1
- 請問 localtime() 為什麼不會造成 memory leak?
- 关于C语言
- 2016第七届蓝桥杯C/C++ B组省赛题解 D题
- c++ 中__declspec 的用法
- STL应用总结
- C++循环冗余检验CRC
- 2016第七届蓝桥杯C/C++ B组省赛题解 C题 (全排列的学习)
- <string> 与<string.h>、<cstring>的区别
- C++primer 练习12.6