目录
单类单继承虚函数下的数据成员布局
类中引入虚函数时,会有额外的成本付出
- 编译的时候,编译器会产生虚函数表
- 对象中会产生 虚函数表指针vptr,用以指向虚函数表的
- 增加或者扩展构造函数,增加给虚函数表指针vptr赋值的代码,让vptr指向虚函数表;
- 如果多重继承,比如继承了2个父类,每个父类都有虚函数的话,每个父类都会有vptr,那继承时,子类就会把这两根vptr都继承过来,如果子类还有自己额外的虚函数的话,子类与第一个基类共用一个vptr
- 析构函数中也被扩展增加了虚函数表指针vptr相关的赋值代码,赋值代码与构造函数中代码相似
class MYACLS public: int m_i; int m_j; virtual void myvirfunc() {} //虚函数 MYACLS() { int abc = 1; //方便加断点 } ~MYACLS() { int def = 0;//方便加断点 } }; int main() { MYACLS myobj; return 1; }
- 调试1
- 调试2
单个类带虚函数的数据成员布局
class MYACLS public: int m_i; int m_j; virtual void myvirfunc() {} //虚函数 MYACLS() { int abc = 1; //方便加断点 } ~MYACLS() { int def = 0;//方便加断点 } }; int main() { cout << sizeof(MYACLS) << endl; printf("MYACLS::m_i = %d\n", &MYACLS::m_i); printf("MYACLS::m_j = %d\n", &MYACLS::m_j); MYACLS myobj; myobj.m_i = 3; myobj.m_j = 6; return 1; }
- 调试
- 输出:
- 单个类带虚函数的数据成员布局
单一继承父类带虚函数的数据成员布局
class Base { public: int m_bi; virtual void mybvirfunc() {} }; class MYACLS :public Base public: int m_i; int m_j; virtual void myvirfunc() {} //虚函数 MYACLS() { int abc = 1; //方便加断点 } ~MYACLS() { int def = 0;//方便加断点 } }; int main() { cout << sizeof(MYACLS) << endl; printf("MYACLS::m_bi = %d\n", &MYACLS::m_bi); printf("MYACLS::m_i = %d\n", &MYACLS::m_i); printf("MYACLS::m_j = %d\n", &MYACLS::m_j); MYACLS myobj; myobj.m_i = 3; myobj.m_j = 6; myobj.m_bi = 9; return 1; }
- 调试
- 输出:
- 单一继承父类带虚函数的数据成员布局
单一继承父类不带虚函数的数据成员布局
class Base { public: int m_bi; }; class MYACLS :public Base public: int m_i; int m_j; virtual void myvirfunc() {} //虚函数 MYACLS() { int abc = 1; //方便加断点 } ~MYACLS() { int def = 0;//方便加断点 } }; int main() { cout << sizeof(MYACLS) << endl; printf("MYACLS::m_bi = %d\n", &MYACLS::m_bi); printf("MYACLS::m_i = %d\n", &MYACLS::m_i); printf("MYACLS::m_j = %d\n", &MYACLS::m_j); MYACLS myobj; myobj.m_i = 3; myobj.m_j = 6; myobj.m_bi = 9; return 1; }
- 调试
- 输出
- 单一继承父类不带虚函数的数据成员布局(不能按输出进行绘制,按调试时的真实分布进行绘制内存图)