非虚拟继承
成都创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都网站设计、做网站、成都外贸网站建设公司、新民网络推广、微信小程序定制开发、新民网络营销、新民企业策划、新民品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们大的嘉奖;成都创新互联公司为所有大学生创业者提供新民建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com【带虚函数的类】
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; }; 虚拟继承编译器为派生类合成的默认构造函数分析 编译器为派生类合成的默认构造函数任务分析: 虚拟继承派生类对象模型分析 创新互联www.cdcxhl.cn,专业提供香港、美国云服务器,动态BGP最优骨干路由自动选择,持续稳定高效的网络助力业务部署。公司持有工信部办法的idc、isp许可证, 机房独有T级流量清洗系统配攻击溯源,准确进行流量调度,确保服务器高可用性。佳节活动现已开启,新人活动云服务器买多久送多久。
分享名称:虚函数——虚表总结-创新互联
网站链接:http://cdkjz.cn/article/dejceh.html