深入理解虚表之非虚拟继承及虚拟继承
来源:互联网 发布:松下机器人示教编程 编辑:程序博客网 时间:2024/05/22 13:28
http://blog.csdn.net/yc2zgh1314/article/details/51166375
非虚拟继承
【带虚函数的类】
- class Base
- {
- public:
- virtual void FunTest1()
- {
- cout<<"Base::FunTest1()"<<endl;
- }
- virtual void FunTest2()
- {
- cout<<"Base::FunTest2()"<<endl;
- }
- int _data1;
- };
- int main()
- {
- Base b;
- b._data1 = 0x01;
- return 0;
- }
Base类没有显式定义自己的构造函数,此时编译器会和成默认的构造函数,
合成的构造函数中主要完成在对象头4个字节中填写虚表地址:
Base类对象最后的模型如下:
注意:同一个类的对象共用同一个虚表
Base b1, b2, b3;
从上述的结果中可以得到印证。
【单继承(派生类中没有虚函数覆盖)】
- class Base
- {
- public:
- virtual void FunTest1()
- {cout<<"Base::FunTest1()"<<endl;}
- virtual void FunTest2()
- {cout<<"Base::FunTest2()"<<endl;}
- int _data1;
- };
- class Derive:public Base
- {
- public:
- virtual void FunTest3()
- {cout<<"Derive::FunTest3()"<<endl;}
- virtual void FunTest4()
- {cout<<"Derive::FunTest4()"<<endl;}
- int _data2;
- };
- //打印虚表
- typedef void (*VtbFun)();
- void PrintVtable()
- {
- cout<<"Derive类的虚函数表:"<<endl;
- Derive d1;
- d1._data1 = 0x01;
- d1._data2 = 0x02;
- int* pVTable = (int*)*(int*)&d1;
- VtbFun FunTest = (VtbFun)*pVTable;
- while(NULL != FunTest)
- {
- FunTest();
- cout<<(int*)FunTest<<endl;
- pVTable += 1;
- FunTest = (VtbFun)*pVTable;
- }
- cout<<"虚表结束:"<<endl;
- }
- 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()"<<endl;
- }
- virtual void FunTest2()
- {
- cout<<"Base::FunTest2()"<<endl;
- }
- int _data1;
- };
- class Derive:public Base
- {
- public:
- virtual void FunTest1()
- {
- cout<<"Derive::FunTest1()"<<endl;
- }
- virtual void FunTest3()
- {
- cout<<"Derive::FunTest3()"<<endl;
- }
- virtual void FunTest4()
- {
- cout<<"Derive::FunTest4()"<<endl;
- }
- int _data2;
- };
- int main()
- {
- PrintVtable();
- return 0;
- }
派生类对象模型及虚表建议规则:
【多继承(派生类不覆盖基类虚函数)】
- class Base
- {
- public:
- virtual void FunTest1()
- {
- cout<<"Base::FunTest1()"<<endl;
- }
- virtual void FunTest2()
- {
- cout<<"Base::FunTest2()"<<endl;
- }
- int _data1;
- };
- class Base1
- {
- public:
- virtual void FunTest3()
- {
- cout<<"Base1::FunTest3()"<<endl;
- }
- virtual void FunTest4()
- {
- cout<<"Base1::FunTest4()"<<endl;
- }
- int _data2;
- };
- class Derive:public Base, public Base1
- {
- public:
- virtual void FunTest5()
- {
- cout<<"Derive::FunTest5()"<<endl;
- }
- int _data3;
- };
- int main()
- {
- cout<<"sizeof(Derive) = "<<sizeof(Derive)<<endl;
- 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()"<<endl;
- }
- virtual void FunTest2()
- {
- cout<<"Base::FunTest2()"<<endl;
- }
- int _data1;
- };
- class Base1
- {
- public:
- virtual void FunTest3()
- {
- cout<<"Base1::FunTest3()"<<endl;
- }
- virtual void FunTest4()
- {
- cout<<"Base1::FunTest4()"<<endl;
- }
- int _data2;
- };
- //这次将继承列表中Base和Base1的位置互换
- class Derive:public Base1, public Base
- {
- public:
- virtual void FunTest1()
- {
- cout<<"Derive::FunTest1()"<<endl;
- }
- virtual void FunTest3()
- {
- cout<<"Derive::FunTest3()"<<endl;
- }
- virtual void FunTest5()
- {
- cout<<"Derive::FunTest5()"<<endl;
- }
- int _data3;
- };
- int main()
- {
- PrintVtable();
- return 0;
- }
此时派生类的对象模型和虚表的结构:
虚拟继承
//没有虚函数覆盖,但派生类有自己的虚函数
- class Base
- {
- public:
- virtual void FunTest1()
- {
- cout<<"Base::FunTest1()"<<endl;
- }
- virtual void FunTest2()
- {
- cout<<"Base::FunTest2()"<<endl;
- }
- int _data1;
- };
- class Derive:virtual public Base
- {
- public:
- virtual void FunTest3()
- {
- cout<<"Derive::FunTest3()"<<endl;
- }
- virtual void FunTest4()
- {
- cout<<"Derive::FunTest4()"<<endl;
- }
- int _data2;
- };
虚拟继承编译器为派生类合成的默认构造函数分析
编译器为派生类合成的默认构造函数任务分析:
虚拟继承派生类对象模型分析
说明:使用环境VS2010,不同版本编译器可能会有差异
说明:使用环境VS2010,不同版本编译器可能会有差异
0 0
- 深入理解虚表之非虚拟继承及虚拟继承
- 深入理解虚表之非虚拟继承及虚拟继承
- c++之虚拟继承
- 虚拟继承和虚表
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承
- 虚拟继承?
- 虚拟继承
- Ubuntu16.04.1如何安装TensorFlow1.1.0(GPU版)
- setsockopt 设置 SO_LINGER 选项
- shell的tomcat部署脚本
- LinkedList
- Java核心技术II:对象流与序列化
- 深入理解虚表之非虚拟继承及虚拟继承
- php使用memcache存储session
- chrome及chromedriver
- 随笔
- 机器学习 之 十大算法
- 成功配置windows-caffe+matlab+cuda6.5+vs2013+opencv2.4.9的艰辛历程
- 洛谷P2722 总分 Score Inflation
- linux使用su切换用户提示:Authentication failure的解决方法
- STM 32之智能温控器