1、带有虚函数的类
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; }
对象模型:
mian函数的反汇编:
如果类中没有自己写构造函数,并且含有虚函数,那么编译器就会合成一个缺省的构造函数。
Base()的构造函数分析:
1>在它的构造函数中主要完成的是:在&b指向的那块空间中,填写了虚指针,
2>注意:虚表是编译器在编译和链接完成之后就已经建立好的,在构造函数中只是将虚表的地址填写到对象的前4个字节。
3>虚表中虚函数地址的存放顺序,是按照它在类中声明的顺序存放的。
4>虚表中最后的00 00 00 00 表示虚表结束(编译器不同就不一定了)
vptr指向虚表:
对象模型:
先是虚函数指针,再是该类的数据成员
2、单继承(派生类中没有虚函数的覆盖)
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的构造函数:
派生类最后的对象模型为:如果派生类没有对基类中的虚函数进行重写时,派生类中的虚表先是基类的虚函数地址,然后再加上自己的虚函数地址。虚函数地址的顺序为在类中声明的顺序。
派生类中Base的虚表
3、单继承(含有虚函数的覆盖)
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()//覆盖基类中的FunTest1 { cout << "Derive::FunTest1()" << endl; } 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() { PrintVtable(); return 0; }
派生类对象模型及虚表建立规则:先将基类的虚表搬移过来,若派生类对基类中的某个函数进行了重写,则会用派生类重写的虚函数的地址替换掉虚表中相应位置基类中虚函数的地址,替换完之后再将派生类自己的虚函数地址按照声明的顺序添加到虚表中
4、多继承(没有虚函数的覆盖)
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; }; 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() { Derive d; d._data1 = 0x01; d._data2 = 0x02; d._data3 = 0x03; PrintVtable(); return 0; }
5、多继承(含有虚函数的覆盖)
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; }; typedef void (*VtbFun)(); void PrintVtable() { cout << "Derive类的虚函数表: " << endl; Derive d1; d1._data1 = 0x01; d1._data2 = 0x02; d1._data3 = 0x03; 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() { PrintVtable(); return 0; }
此时派生类的对象模型和虚表的结构:
派生类虚表建立过程:先建立和Base1相同的部分,在Derive中对FunTest3进行了重写,所以替换掉虚表中原来的Base1::FunTest3改为了Derive::FunTest3,为了提高访问速度,将自己特有的虚函数加在第一份虚表的后面,建立Base虚表的过程与Base1相同。
6、虚拟继承
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; }; 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() { PrintVtable(); return 0; }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。