多态的类,内存布局是怎样的
关于类的内存布局主要是考某个类所占的内存大小,通过以下几个案例加以分析
虚继承:如果是虚继承,那么就会为这个类创建一个虚表指针,占用4个字节
#include<iostream> class A{ public: int a; };//sizeof(A) = 4,因为a是整形,占用4个字节 class B:virtual piblic A{ public: int b; };//sizeof(B) = 4(A副本) + 4(虚表指针占用4字节) +4(变量b占4个字节) = 12 class C:virtual public B{ };//sizeof(c) = 12(B的副本) + 4(虚表指针) = 16 //如果这里改为直接继承,那么sizeof(C)为12,因为此时没有虚表指针了
多重继承:如果是以虚继承实现的多继承,记得减掉基类的副本
#include<iostream> class A{ public: int a; };//sizeof(A) = 4 class B:virtual piblic A{ };//sizeof(B) = 4+4 = 8 class C:virtual public A{ };//sizeof(C) = 4+4 = 8 class D:public B, public c{ };//sizeof(D) = 8+8-4 = 12 //或者 sizeof(D) 4+4+4 = 12
普通继承(含有:空类、虚函数)
class A //result=1 空类所占空间的大小为1 { }; class B //result=8 1+4 字节对齐后为 8 { char ch; virtual void func0() { } }; class C //result=8 1+1+4 字节对齐后为 8,没有继承的,此时类里即使出现多个虚函数,也只有一个虚指针 { char ch1; char ch2; virtual void func() { } //也只有一个虚指针 virtual void func1() { } //也只有一个虚指针 }; class D: public A, public C //result=12 8(C的副本)+4(整形变量 d占用4字节)=12 { int d; virtual void func() { } //继承了C,C里已经有一个虚指针,此时D自己有虚函数, virtual void func1() { } //也不会创建另一个虚指针,所以D本身就变量d需要4字节 }; class E: public B, public C //result=20 8( B的副本)+8(C的副本)+4(E本身)=20 { int e; virtual void func0() { } //同理,E不会创建另一个虚指针,所以E本身就变量e需 virtual void func1() { } //要4字节 };
虚函数(多继承和虚函数)
class CommonBase { int co; };// size = 4 class Base1: virtual public CommonBase { public: virtual void print1() { } virtual void print2() { } private: int b1; };//4(父类副本)+4(自己有虚函数,加1个虚指针空间)+4(自身变量b1)+4(虚继承再加1个虚指针空间)=16 class Base2: virtual public CommonBase { public: virtual void dump1() { } virtual void dump2() { } private: int b2; };//同理16 class Derived: public Base1, public Base2 { public: void print2() { } void dump2() { } private: int d; };//16+16-4+4=32
- 前辈总结说:如果不是虚继承的类,即便有虚函数也不会因此增加存储空间,如果是虚继承的类,没有虚函数就添加一个虚指针空间,有虚函数不论多少个,就添加两个虚指针空间。
- 如果此时类里有一个或多个虚函数,那么需要加1个虚指针空间,如果还是虚继承,那么需要再加1个虚指针空间,最多就2个虚指针空间。
- 虚继承与虚函数
class A { public: virtual void aa() { } virtual void aa2() { } //如果此时类里有一个或多个虚函数,那么需要加1个虚指针空间 private: char ch[3]; }; // 1+4 =补齐= 8 class B: virtual public A //如果还是虚继承,那么需要再加1个虚指针空间,最多就2个虚指//针空间。 { public: virtual void bb() { } virtual void bb2() { } }; // 8(副本)+4(虚继承)+4(虚指针)= 16
- 总结:如果此时类里有一个或多个虚函数,那么需要加1个虚指针空间,如果还是虚继承,那么需要再加1个虚指针空间,最多就2个虚指针空间。