文章連結:http://blog.csdn.net/haoel/article/details/1948051
C++中的虛函數的作用主要是實現了多態的機制。關於多態,簡而言之就是用父類型別的指標指向其子類的執行個體,然後通過父類的指標調用實際子類的成員函數。
對C++ 瞭解的人都應該知道虛函數(Virtual Function)是通過一張虛函數表(Virtual Table)來實現的。簡稱為V-Table。在這個表中,主是要一個類的虛函數的地址表,這張表解決了繼承、覆蓋的問題,保證其內容真實反應實際的函數。這樣,在有虛函數的類的執行個體中這個表被分配在了這個執行個體的記憶體中。
C++的編譯器應該是保證虛函數表的指標存在於對象執行個體中最前面的位置。
代碼:
class Base{public:virtual void f() { cout << "Base::f" << endl; }virtual void g() { cout << "Base::g" << endl; }virtual void h() { cout << "Base::h" << endl; }virtual ~Base() {}};typedef void(*Fun) (void);int main(){Base b;Fun pFun = NULL;cout << "虛函數表地址" << (int *)(&b) << endl;cout << "虛函數表--第一個虛函數地址" << (int*)*(int*)(&b)<< endl;pFun = (Fun)*(int *)*(int*)(&b);pFun();return 0;}
輸出:
虛函數表地址:0x22ff48虛函數表--第一個虛函數地址:0x4041d0Base::f
代碼如下:
using namespace std;typedef void(*Fun) (void);class Base{public:virtual void f() { cout << "Base::f" << endl; }virtual void g() { cout << "Base::g" << endl; }virtual void h() { cout << "Base::h" << endl; }virtual ~Base() {}};class Derived: public Base{public:virtual void f1() { cout << "Derived::f1" << endl; }virtual void g1() { cout << "Derived::g1" << endl; }virtual void h1() { cout << "Derived::h1" << endl; }virtual ~Derived() {}};int main(){Base b;Derived d;Fun pFun = NULL;int **pVtab = (int**)(&d);for(int i = 0; NULL != (Fun)pVtab[0][i] && i<3; i++){pFun = (Fun)pVtab[0][i];pFun();}return 0;}
按文章所述,衍生類別對象d的虛函數表如下:
但未得到驗證。但代碼中for迴圈的條件為"i<3"時,可以輸出繼承自Base類的3個虛函數。
但將for迴圈的條件改為”i<6”時,執行時會報讀記憶體錯誤,在gcc和VS2010下都是如此。是在VS2010下得到的虛函數表:
代碼如下:
#include <iostream>using namespace std;typedef void(*Fun) (void);class Base{public:virtual void f() { cout << "Base::f" << endl; }virtual void g() { cout << "Base::g" << endl; }virtual void h() { cout << "Base::h" << endl; }virtual ~Base() {}};class Derived: public Base{public:virtual void f1() { cout << "Derived::f1" << endl; }virtual void g1() { cout << "Derived::g1" << endl; }virtual void h1() { cout << "Derived::h1" << endl; }virtual void f() { cout << "Derived::f" << endl; }virtual void g() { cout << "Derived::g" << endl; }virtual void h() { cout << "Derived::h" << endl; }virtual ~Derived() {}};int main(){Base b;Derived d;Fun pFun = NULL;int **pVtab = (int**)(&d);for(int i = 0; NULL != (Fun)pVtab[0][i] && i<6; i++){pFun = (Fun)pVtab[0][i];pFun();}return 0;}
按文章所述,衍生類別對象d的虛函數表如下:
代碼中for迴圈的條件為"i<3"時,可以輸出衍生類別d重載的三個虛函數,說明衍生類別的f(), g(), h()函數將繼承自Base類的這個三個函數覆蓋。
但將for迴圈的條件改為”i<6”時,執行時仍會報讀記憶體錯誤。是在VS2010下得到的虛函數表:
代碼如下:
#include <iostream>using namespace std;typedef void(*Fun) (void);class Base1{public:virtual void f() { cout << "Base1::f" << endl; }virtual void g() { cout << "Base1::g" << endl; }virtual void h() { cout << "Base1::h" << endl; }virtual ~Base1() {}};class Base2{public:virtual void f() { cout << "Base2::f" << endl; }virtual void g() { cout << "Base2::g" << endl; }virtual void h() { cout << "Base2::h" << endl; }virtual ~Base2() {}};class Base3{public:virtual void f() { cout << "Base3::f" << endl; }virtual void g() { cout << "Base3::g" << endl; }virtual ~Base3() {}};class Derived: public Base1, public Base2, public Base3{public:virtual void f1() { cout << "Derived::f1" << endl; }virtual void g1() { cout << "Derived::g1" << endl; }virtual void h1() { cout << "Derived::h1" << endl; }virtual ~Derived() {}};int main(){Derived d;Fun pFun = NULL;int **pVtab = (int**)(&d);for(int i = 0; i<3; i++){for(int j = 0; NULL != (Fun)pVtab[i][j] && i<6; j++){pFun = (Fun)pVtab[i][j];pFun();}}return 0;}
按文章所述,衍生類別對象d的虛函數表如下: