当前位置:编程学习 > C/C++ >>

C++类的大小

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

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: public A 

public: 
    virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

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。

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: public A 

public: 
    //virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

VS和gcc下结果:

A's size is 8
B's size is 8

说明:类B看上去没有虚函数,但实际上它有,只是没有重写,因为public继承,所以有从A继承过来的虚函数A::aa(),实际上类A和类B的虚函数表里的函数都是A::aa()。
[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
    virtual void aa2(){} 
private: 
    char k[3]; 
}; 
 
class B: public A 

public: 
    virtual void bb(){} 
    virtual void bb2(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

vs和gcc下
执行结果:

A's size is 8
B's size is 8

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

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: virtual public A 

public: 
    //virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

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。

[cpp] 
#include<iostream> 
using namespace std; 
class A 

public: 
    virtual void aa(){} 
private: 
    char k[3]; 
}; 
 
class B: public virtual A 

public: 
    virtual void bb(){} 
}; 
 
int main() 

    cout<<"A's size is "<<sizeof(A)<<endl; 
    cout<<"B's size is "<<sizeof(B)<<endl; 
    return 0; 

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字节什么也没有。

关于虚函数、多继承、虚继承,可以看《More Effective C++》:理解虚拟函数、多继承、虚基类和RTTI所需的代价

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,