C++里的继承和多态(下)——单继承、多继承、菱形继承(含虚拟函数的继承)
1、带有虚函数的类
classBase{public:virtualvoidFunTest1(){cout<<"Base::FunTest1()"<<endl;}virtualvoidFunTest2(){cout<<"Base::FunTest2()"<<endl;}int_data1;};intmain(){Baseb;b._data1=0x01;return0;}
对象模型:
mian函数的反汇编:
如果类中没有自己写构造函数,并且含有虚函数,那么编译器就会合成一个缺省的构造函数。
Base()的构造函数分析:
1>在它的构造函数中主要完成的是:在&b指向的那块空间中,填写了虚指针,
2>注意:虚表是编译器在编译和链接完成之后就已经建立好的,在构造函数中只是将虚表的地址填写到对象的前4个字节。
3>虚表中虚函数地址的存放顺序,是按照它在类中声明的顺序存放的。
4>虚表中最后的00 00 00 00 表示虚表结束(编译器不同就不一定了)
vptr指向虚表:
对象模型:
先是虚函数指针,再是该类的数据成员
2、单继承(派生类中没有虚函数的覆盖)
classBase{public:virtualvoidFunTest1(){cout<<"Base::FunTest1()"<<endl;}virtualvoidFunTest2(){cout<<"Base::FunTest2()"<<endl;}int_data1;};classDerive:publicBase{public:virtualvoidFunTest3(){cout<<"Derive::FunTest3()"<<endl;}virtualvoidFunTest4(){cout<<"Derive::FunTest4()"<<endl;}int_data2;};//打印虚表typedefvoid(*VtbFun)();voidPrintVtable(){cout<<"Derive类的虚函数表:"<<endl;Derived1;d1._data1=0x01;d1._data2=0x02;int*pVTable=(int*)*(int*)&d1;VtbFunFunTest=(VtbFun)*pVTable;while(NULL!=FunTest){FunTest();cout<<(int*)FunTest<<endl;pVTable+=1;FunTest=(VtbFun)*pVTable;}cout<<"虚表结束:"<<endl;}intmain(){Baseb1;Derived1;return0;}
主要还是完成虚指针的填写
在是Derive的构造函数:
派生类最后的对象模型为:如果派生类没有对基类中的虚函数进行重写时,派生类中的虚表先是基类的虚函数地址,然后再加上自己的虚函数地址。虚函数地址的顺序为在类中声明的顺序。
派生类中Base的虚表
3、单继承(含有虚函数的覆盖)
classBase{public:virtualvoidFunTest1(){cout<<"Base::FunTest1()"<<endl;}virtualvoidFunTest2(){cout<<"Base::FunTest2()"<<endl;}int_data1;};classDerive:publicBase{public:virtualvoidFunTest1()//覆盖基类中的FunTest1{cout<<"Derive::FunTest1()"<<endl;}virtualvoidFunTest3(){cout<<"Derive::FunTest3()"<<endl;}virtualvoidFunTest4(){cout<<"Derive::FunTest4()"<<endl;}int_data2;};typedefvoid(*VtbFun)();voidPrintVtable(){cout<<"Derive类的虚函数表:"<<endl;Derived1;d1._data1=0x01;d1._data2=0x02;int*pVTable=(int*)*(int*)&d1;VtbFunFunTest=(VtbFun)*pVTable;while(NULL!=FunTest){FunTest();cout<<(int*)FunTest<<endl;pVTable+=1;FunTest=(VtbFun)*pVTable;}cout<<"虚表结束:"<<endl;}intmain(){PrintVtable();return0;}
派生类对象模型及虚表建立规则:先将基类的虚表搬移过来,若派生类对基类中的某个函数进行了重写,则会用派生类重写的虚函数的地址替换掉虚表中相应位置基类中虚函数的地址,替换完之后再将派生类自己的虚函数地址按照声明的顺序添加到虚表中
4、多继承(没有虚函数的覆盖)
classBase{public:virtualvoidFunTest1(){cout<<"Base::FunTest1()"<<endl;}virtualvoidFunTest2(){cout<<"Base::FunTest2()"<<endl;}int_data1;};classBase1{public:virtualvoidFunTest3(){cout<<"Base1::FunTest3()"<<endl;}virtualvoidFunTest4(){cout<<"Base1::FunTest4()"<<endl;}int_data2;};classDerive:publicBase,publicBase1{public:virtualvoidFunTest5(){cout<<"Derive::FunTest5()"<<endl;}int_data3;};typedefvoid(*VtbFun)();voidPrintVtable(){cout<<"Derive类的虚函数表:"<<endl;Derived1;d1._data1=0x01;d1._data2=0x02;int*pVTable=(int*)*(int*)&d1;VtbFunFunTest=(VtbFun)*pVTable;while(NULL!=FunTest){FunTest();cout<<(int*)FunTest<<endl;pVTable+=1;FunTest=(VtbFun)*pVTable;}cout<<"虚表结束."<<endl;}intmain(){Derived;d._data1=0x01;d._data2=0x02;d._data3=0x03;PrintVtable();return0;}
5、多继承(含有虚函数的覆盖)
classBase{public:virtualvoidFunTest1(){cout<<"Base::FunTest1()"<<endl;}virtualvoidFunTest2(){cout<<"Base::FunTest2()"<<endl;}int_data1;};classBase1{public:virtualvoidFunTest3(){cout<<"Base1::FunTest3()"<<endl;}virtualvoidFunTest4(){cout<<"Base1::FunTest4()"<<endl;}int_data2;};//这次将继承列表中Base和Base1的位置互换classDerive:publicBase1,publicBase{public:virtualvoidFunTest1(){cout<<"Derive::FunTest1()"<<endl;}virtualvoidFunTest3(){cout<<"Derive::FunTest3()"<<endl;}virtualvoidFunTest5(){cout<<"Derive::FunTest5()"<<endl;}int_data3;};typedefvoid(*VtbFun)();voidPrintVtable(){cout<<"Derive类的虚函数表:"<<endl;Derived1;d1._data1=0x01;d1._data2=0x02;d1._data3=0x03;int*pVTable=(int*)*(int*)&d1;VtbFunFunTest=(VtbFun)*pVTable;while(NULL!=FunTest){FunTest();cout<<(int*)FunTest<<endl;pVTable+=1;FunTest=(VtbFun)*pVTable;}cout<<"虚表结束."<<endl;}intmain(){PrintVtable();return0;}
此时派生类的对象模型和虚表的结构:
派生类虚表建立过程:先建立和Base1相同的部分,在Derive中对FunTest3进行了重写,所以替换掉虚表中原来的Base1::FunTest3改为了Derive::FunTest3,为了提高访问速度,将自己特有的虚函数加在第一份虚表的后面,建立Base虚表的过程与Base1相同。
6、虚拟继承
classBase{public:virtualvoidFunTest1(){cout<<"Base::FunTest1()"<<endl;}virtualvoidFunTest2(){cout<<"Base::FunTest2()"<<endl;}int_data1;};classDerive:virtualpublicBase{public:virtualvoidFunTest3(){cout<<"Derive::FunTest3()"<<endl;}virtualvoidFunTest4(){cout<<"Derive::FunTest4()"<<endl;}int_data2;};typedefvoid(*VtbFun)();voidPrintVtable(){cout<<"Derive类的虚函数表:"<<endl;Derived1;d1._data1=0x01;d1._data2=0x02;int*pVTable=(int*)*(int*)&d1;VtbFunFunTest=(VtbFun)*pVTable;while(NULL!=FunTest){FunTest();cout<<(int*)FunTest<<endl;pVTable+=1;FunTest=(VtbFun)*pVTable;}cout<<"虚表结束:"<<endl;}intmain(){PrintVtable();return0;}
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。