博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++类的大小(转)
阅读量:7174 次
发布时间:2019-06-29

本文共 3380 字,大约阅读时间需要 11 分钟。

一个空类class A{};的大小为什么是1,因为如果不是1,当定义这个类的对象数组时候A objects[5]; objects[0]和objects[1]就在同一个地址处,就无法区分。

单继承

1 #include
2 using namespace std; 3 class A 4 { 5 public: 6 virtual void aa(){} 7 private: 8 char k[3]; 9 };10 11 class B: public A12 {13 public:14 virtual void bb(){}15 };16 17 int main()18 {19 cout<<"A's size is "<
<

 

vs和gcc下

执行结果:A's size is 8
              B's size is 8

说明:有虚函数的类有个virtual table(虚函数表),里面包含了类的所有虚函数,类中有个virtual table pointers,通常成为vptr指向这个virtual table,占用4个字节的大小。成员类B public继承于A,类B的虚函数表里实际上有两个虚函数A::aa()和B::bb(),类B的大小等于char k[3]的大小加上一个指向虚函数表指针vptr的大小,考虑内存对齐为8。

1 #include
2 using namespace std; 3 class A 4 { 5 public: 6 virtual void aa(){} 7 private: 8 char k[3]; 9 };10 11 class B: public A12 {13 public:14 //virtual void bb(){}15 };16 17 int main()18 {19 cout<<"A's size is "<
<

 

vs和gcc下

执行结果:A's size is 8
              B's size is 8
说明:类B看上去没有虚函数,但实际上它有,只是没有重写,因为public继承,所以有从A继承过来的虚函数A::aa(),实际上类A和类B的虚函数表里的函数都是A::aa()。

1 #include
2 using namespace std; 3 class A 4 { 5 public: 6 virtual void aa(){} 7 virtual void aa2(){} 8 private: 9 char k[3];10 };11 12 class B: public A13 {14 public:15 virtual void bb(){}16 virtual void bb2(){}17 };18 19 int main()20 {21 cout<<"A's size is "<
<

 

vs和gcc下

执行结果:A's size is 8
              B's size is 8

说明:一个类里若有虚函数,无论有多少个虚函数都只有一个指向虚表的指针,虚表中的每一个表项保存着一个虚函数的入口地址。当调用虚函数时,先找到虚表中它对应的表项,找到入口地址再执行。对于直接单继承,无论类B中有无虚函数,由于它继承了类A,且类A里含有虚函数,因此如果类B有虚函数,那么它和类A的是在同一个属于类B的虚表里,这张虚表的虚函数为A::aa()、A::aa2()、B::bb()、B::bb2()。注意:类A里的私有成员在类B里仍占有内存。

多继承

1 #include
2 using namespace std; 3 class A 4 { 5 public: 6 virtual void aa(){} 7 virtual void aa2(){} 8 private: 9 char k[3];10 };11 12 class B13 {14 public:15 virtual void bb(){}16 virtual void bb2(){}17 };18 19 class C: public A,public B20 {21 public:22 virtual void aa(){} //重写了A的aa()23 virtual void cc(){}24 };25 26 int main()27 {28 cout<<"A's size is "<
<

 

vs和gcc下

执行结果:A's size is 8
          B's size is 4
          B's size is 12

说明:类A和B的大小就不解释了,参照上面。类C多重继承于A和B(有虚函数覆盖),那么类C的大小是多少?先看成员变量,有一个继承A的char k[3]。再看虚函数,类C的中虚函数是怎么分布的?先有一个虚函数表,里面有继承于类A的虚函数和C自己的虚函数(C::aa(), A::aa2(), C::cc()),如果C没有重写aa(),那么第一个虚函数就是A::aa(),接着有第二张虚函数表是继承包含类B的虚函数B::bb()、B::bb2()(类C没有重写B的虚函数)。总的大小就是2张虚表的大小(也即两个虚函数指针的大小)8字节加上3字节的k[3],考虑内存对齐,就是12字节。

虚继承

1 #include
2 using namespace std; 3 class A 4 { 5 public: 6 virtual void aa(){} 7 private: 8 char k[3]; 9 };10 11 class B: virtual public A12 {13 public:14 //virtual void bb(){}15 };16 17 int main()18 {19 cout<<"A's size is "<
<

 

vs和gcc下

执行结果:A's size is 8
              B's size is 12
说明:类B里包含,继承的char k[3],继承的虚函数,类B的虚函数表里有A::aa(),因为是虚继承,还有一个指向父类的指针,该指针为指向虚基类的指针(Pointer to virtual base class)。考虑内存对齐,总大小为12。

1 #include
2 using namespace std; 3 class A 4 { 5 public: 6 virtual void aa(){} 7 private: 8 char k[3]; 9 };10 11 class B: public virtual A12 {13 public:14 virtual void bb(){}15 };16 17 int main()18 {19 cout<<"A's size is "<
<

 

VS执行结果:A's size is 8

                  B's size is 16

gcc执行结果:A's size is 8

                  B's size is 12

说明:对于虚继承,类B虚继承类A时,首先要通过加入一个指针来指向父类A,该指针被称为虚基类指针。然后包含从父类继承过来的3个char,再加上一个虚函数指针。考虑内存对齐,在gcc下结果是4+4+4=12。在VS下,结果是16,why?这一题和上一题区别只是在类B中添加了一个虚函数,但是两个题目中类B都有虚函数表。在VS下调试查看汇编代码,发现多出来的4字节什么也没有。

 

转自:

转载地址:http://fqbzm.baihongyu.com/

你可能感兴趣的文章
内联表达式
查看>>
手动添加数据源时DataGridViewComboBoxCell值出问题解决方法
查看>>
函数声明优先于变量
查看>>
HDU-1003 Max Sum 动态规划
查看>>
Silverlight.XNA(C#)跨平台3D游戏研发手记:(九)3D 骨骼动画
查看>>
在.NET外散步之我爱贪吃蛇Python -常见语句(神奇的else)
查看>>
Known Issues
查看>>
文件相关操作工具类——FileUtils.java
查看>>
原:视频直播技术中的参考技术网页
查看>>
linq教程
查看>>
requests从api中获取数据并存放到mysql中
查看>>
23种设计模式之组合模式(Composite)
查看>>
button按钮点击不刷新(前端交流学习:452892873)
查看>>
安卓 使用Gradle生成正式签名apk文件
查看>>
@Html.Raw()
查看>>
ES6 Proxy
查看>>
图的基本算法(BFS和DFS)
查看>>
Linux时区详解
查看>>
61.node.js开发错误——Error: Connection strategy not found
查看>>
算法逆向第一篇——简单算法逆向
查看>>