虚函数——虚表总结
非虚拟继承
公司主营业务:网站设计制作、网站建设、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出大化免费做网站回馈大家。
【带虚函数的类】
class Base
{
public:
virtual void FunTest1()
{
cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; int main() { Base b; b._data1 = 0x01; return 0; } Base类没有显式定义自己的构造函数,此时编译器会和成默认的构造函数, 合成的构造函数中主要完成在对象头4个字节中填写虚表地址: Base类对象最后的模型如下: 注意:同一个类的对象共用同一个虚表 从上述的结果中可以得到印证。 【单继承(派生类中没有虚函数覆盖)】 class Base { public: virtual void FunTest1() {cout<<"Base::FunTest1()"< virtual void FunTest2() {cout<<"Base::FunTest2()"< int _data1; }; class Derive:public Base { public: virtual void FunTest3() {cout<<"Derive::FunTest3()"< virtual void FunTest4() {cout<<"Derive::FunTest4()"< int _data2; }; //打印虚表 typedef void (*VtbFun)(); void PrintVtable() { cout<<"Derive类的虚函数表:"< Derive d1; d1._data1 = 0x01; d1._data2 = 0x02; int* pVTable = (int*)*(int*)&d1; VtbFun FunTest = (VtbFun)*pVTable; while(NULL != FunTest) { FunTest(); cout<<(int*)FunTest< pVTable += 1; FunTest = (VtbFun)*pVTable; } cout<<"虚表结束:"< } int main() { Base b1; Derive d1; return 0; } 按照如上分析的顺序,探索下单继承下派生类对象模型以及虚表 首先看看编译器为派生类合成的缺省构造函数: 派生类构造函数中进行了如下事情: Derive d1; d1._data1 = 0x01; d1._data2 = 0x02; 派生类最后的对象模型为: 【单继承(派生类中有虚函数覆盖)】 class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Derive:public Base { public: virtual void FunTest1() { cout<<"Derive::FunTest1()"< } virtual void FunTest3() { cout<<"Derive::FunTest3()"< } virtual void FunTest4() { cout<<"Derive::FunTest4()"< } int _data2; }; int main() { PrintVtable(); return 0; } 派生类对象模型及虚表建议规则: 【多继承(派生类不覆盖基类虚函数)】 class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Base1 { public: virtual void FunTest3() { cout<<"Base1::FunTest3()"< } virtual void FunTest4() { cout<<"Base1::FunTest4()"< } int _data2; }; class Derive:public Base, public Base1 { public: virtual void FunTest5() { cout<<"Derive::FunTest5()"< } int _data3; }; int main() { cout<<"sizeof(Derive) = "< Derive d; d._data1 = 0x01; d._data2 = 0x02; d._data3 = 0x03; PrintVtable(); return 0; } 同样:看看编译器合成的派生类的对象做了什么工作 观察下派生类的对象模型和虚表的建立过程 从上面的结果可以看出,Derive类自己特有的虚函数直接添加在Base类对应虚函数表最后的位置,大家可将Base和Base1的顺序交换验证下。 【多继承(派生类覆盖基类虚函数)】 class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Base1 { public: virtual void FunTest3() { cout<<"Base1::FunTest3()"< } virtual void FunTest4() { cout<<"Base1::FunTest4()"< } int _data2; }; //这次将继承列表中Base和Base1的位置互换 class Derive:public Base1, public Base { public: virtual void FunTest1() { cout<<"Derive::FunTest1()"< } virtual void FunTest3() { cout<<"Derive::FunTest3()"< } virtual void FunTest5() { cout<<"Derive::FunTest5()"< } int _data3; }; int main() { PrintVtable(); return 0; } 此时派生类的对象模型和虚表的结构: 虚拟继承 //没有虚函数覆盖,但派生类有自己的虚函数 class Base { public: virtual void FunTest1() { cout<<"Base::FunTest1()"< } virtual void FunTest2() { cout<<"Base::FunTest2()"< } int _data1; }; class Derive:virtual public Base { public: virtual void FunTest3() { cout<<"Derive::FunTest3()"< } virtual void FunTest4() { cout<<"Derive::FunTest4()"< } int _data2; }; 虚拟继承编译器为派生类合成的默认构造函数分析 编译器为派生类合成的默认构造函数任务分析: 虚拟继承派生类对象模型分析
当前标题:虚函数——虚表总结
当前地址:http://hbruida.cn/article/jhojsg.html