I. Definition virtual function
Modified keyword virtual member function, the purpose is to achieve polymorphism
ps:
About polymorphic {separate interface from implementation, a pointer to the parent class instance of a subclass and member functions by calling the parent class pointer subclass, which would allow the parent pointer has a variety of forms, so called polymorphism]
II. Vtable
The address table is a table of a class virtual functions, and inheritance for solving the problem coverage
1 has virtual functions have vtable
2. All objects vtable belong to the class, then the class virtual function table by the virtual function table pointer of the shared classes
3. The role of the virtual function table: When using a parent class pointer to operate subclass object, like a virtual table, like the map indicating the actual function should be called
4.c ++ compiler guarantees vtable pointer exists in the foremost position object instance (in order to ensure the performance of the function table obtained in the case of multiple inheritance inheritance or multilayer), which means that we can address through an object instance to obtain the virtual function table, and then can traverse the virtual function pointer wherein, in response to the virtual function call and
ps: Multiple inheritance: a plurality of parent classes, the multilayer to inherit: there is the parent class parent class
[Virtual function table by traversing virtual function pointer, the virtual function call response]
#include<bits/stdc++.h> using namespace std; class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << "Base::g" << endl; } virtual void h() { cout << "Base::h" << endl; } }; typedef void (* Fun) ( void ); Base B; Fun pFun = NULL; int main () { COUT << " virtual function table address: " << ( int *) (& B) << endl; COUT << " vtable - first address of a function: " << ( int *) * ( int *) (& B) << endl; // virtual function is called by the virtual function table pFun = (Fun) * (( int *) * ( int *) (& B)); // Base :: F () pFun (); pFun =(Fun)*((int*)*(int*)(&b)+1); // Base::g() pFun(); pFun =(Fun)*((int*)*(int*)(&b)+2); // Base::h() pFun(); }
result:
Virtual function table address: 0x477008 virtual function table - the first address of a function: 0x473668 Base :: F Base G :: Base :: H
The above is no succession
1. single virtual function inherited without coverage
1) into the virtual function table in declaration order
2) the former parent class virtual function, virtual function in the subclass
3) the end of the end-point identifier number virtual function table, different values at different compilers
#include<bits/stdc++.h> using namespace std; class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << "Base::g" << endl; } virtual void h() { cout << "Base::h" << endl; } }; class Base_son:public Base { public: virtual void f1() { cout << "Base_son::f1" << endl; } virtual void g1() { cout << "Base_son::g1" << endl; } virtual void h1() { cout << "Base_son::h1" << endl; } }; typedef void(*Fun)(void); Base_son d; Fun pFun = NULL; int main() { cout << "虚函数表地址:" << (int*)(&d) << endl; cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&d) << endl; //通过虚函数表调用虚函数 pFun = (Fun)*((int*)*(int*)(&d)); // Base::f() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+1); // Base::g() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+2); // Base::h() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+3); // Base_son::f1() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+4); // Base_son::g1() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+5); // Base_son::h1() pFun(); return 0; }
结果:
虚函数表地址:0x477008 虚函数表 — 第一个函数地址:0x473668 Base::f Base::g Base::h Base_son::f1 Base_son::g1 Base_son::h1
2.单层继承有虚函数覆盖的情况
1)覆盖的f()函数被放到了虚函数表中原父类虚函数的位置
2)没有被覆盖的函数没有变化
#include<bits/stdc++.h> using namespace std; class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << "Base::g" << endl; } virtual void h() { cout << "Base::h" << endl; } }; class Base_son:public Base { public: virtual void f() { cout << "Base_son::f" << endl; } virtual void g1() { cout << "Base_son::g1" << endl; } virtual void h1() { cout << "Base_son::h1" << endl; } }; typedef void(*Fun)(void); Base_son d; Fun pFun = NULL; int main() { cout << "虚函数表地址:" << (int*)(&d) << endl; cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&d) << endl; //通过虚函数表调用虚函数 pFun = (Fun)*((int*)*(int*)(&d)); // Base_son::f() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+1); // Base::g() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+2); // Base::h() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+3); // Base_son::g1() pFun(); pFun =(Fun)*((int*)*(int*)(&d)+4); // Base_son::h1() pFun(); return 0; }
结果:
虚函数表地址:0x477008 虚函数表 — 第一个函数地址:0x473650 Base_son::f Base::g Base::h Base_son::g1 Base_son::h1
通过父类指针指向子类实例,子类覆盖父类方法,然后调用子类的方法,这样就实现了多态
3.多重继承无虚函数覆盖
1)每个父类都有自己的虚函数表
2)子类的虚函数被放到第一个父类的虚函数表中
这样做是为了解决不同的父类类型指针指向同一个子类实例,而能够调用到实际的函数
4.多重继承存在虚函数覆盖
1)父类虚函数表中被覆盖的虚函数全部被替换成了子类的覆盖虚函数
这样我们就通过父类指向子类从而访问子类的f()了
Derive d; Base1 *b1 = &d; Base2 *b2 = &d; Base3 *b3 = &d; b1->f(); //Derive::f() b2->f(); //Derive::f() b3->f(); //Derive::f() b1->g(); //Base1::g() b2->g(); //Base2::g() b3->g(); //Base3::g()
使用虚函数表可以做一些违反c++语义的事情:
1)通过父类指针访问子类自己的虚函数
子类的虚函数X在父类中没有,所以子类的虚函数X没有覆盖父类的虚函数,但是如果我们通过父类的指针来访问子类自己的虚函数的编译器会报错
Base1 *b1 = new Derive(); b1->f1(); //编译出错
但是我们通过虚函数表可以做到这种违背C++语义的事情:使用父类指针访问子类自己的虚函数
2)访问父类non-public的虚函数
如果父类的虚函数是private或protected的,但是这些feipublic的父类虚函数同样会存在于虚函数表中,所以我们可以通过访问虚函数表访问到这些虚函数
附上多重继承有虚函数覆盖的样例代码:
#include <iostream> using namespace std; class Base1 { public: virtual void f() { cout << "Base1::f" << endl; } virtual void g() { cout << "Base1::g" << endl; } virtual void h() { cout << "Base1::h" << endl; } }; class Base2 { public: virtual void f() { cout << "Base2::f" << endl; } virtual void g() { cout << "Base2::g" << endl; } virtual void h() { cout << "Base2::h" << endl; } }; class Base3 { public: virtual void f() { cout << "Base3::f" << endl; } virtual void g() { cout << "Base3::g" << endl; } virtual void h() { cout << "Base3::h" << endl; } }; class Derive : public Base1, public Base2, public Base3 { public: virtual void f() { cout << "Derive::f" << endl; } virtual void g1() { cout << "Derive::g1" << endl; } }; typedef void(*Fun)(void); int main() { Fun pFun = NULL; Derive d; int** pVtab = (int**)&d; //Base1's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+0); pFun = (Fun)pVtab[0][0]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+1); pFun = (Fun)pVtab[0][1]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+2); pFun = (Fun)pVtab[0][2]; pFun(); //Derive's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+3); pFun = (Fun)pVtab[0][3]; pFun(); //The tail of the vtable pFun = (Fun)pVtab[0][4]; cout<<pFun<<endl; //Base2's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0); pFun = (Fun)pVtab[1][0]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1); pFun = (Fun)pVtab[1][1]; pFun(); pFun = (Fun)pVtab[1][2]; pFun(); //The tail of the vtable pFun = (Fun)pVtab[1][3]; cout<<pFun<<endl; //Base3's vtable //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0); pFun = (Fun)pVtab[2][0]; pFun(); //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1); pFun = (Fun)pVtab[2][1]; pFun(); pFun = (Fun)pVtab[2][2]; pFun(); //The tail of the vtable pFun = (Fun)pVtab[2][3]; cout<<pFun<<endl; return 0; }
About virtual function and normal function:
1. The class virtual function is dynamically generated by the access point to the virtual function table memory is not allocated for the object class, no virtual function table, can not access the virtual function
2. Class ordinary function to generate a static, not allocate an object class may access
Reference: mouse left ear: C ++ virtual function table parsing