引入:這段時間一直在思考虛函數表的問題,同時也想知道虛函數表是在什么時候產生的
本人是在VS2010的環境下,如有錯誤歡迎指出,謝謝。
觀察代碼
#include<stdio.h> #include<iostream> class A{ public:A(); virtual~A(); void fun1(){ printf("123"); } }; A::A(){ printf("new A\n"); } A::~A(){ printf("Delete class A\n"); } class B : public A { public:B(); ~B(); void fun2(){ printf("123456"); } }; B::B(){ printf("new B\n"); } B::~B(){ printf("Delete class B\n"); } class C : public B { public:C(); ~C(); void fun2(){ printf("123456"); } }; C::C(){ printf("new C\n"); } C::~C(){ printf("Delete class C\n"); } int main(){ A *a=new A; //A *a=new C; delete a; getchar(); return 0; }
如果虛函數表是在運行的時候產生的話,那么這個代碼的話運行到A *a=new A的時候應該會在內存中產生與類A有關的虛函數表,讓我們觀察下虛函數表的情況:
我們發現這里有A的虛函數表,還有B的虛函數表,在觀察下還會發下C的虛函數表。
思考下為什么要怎么設計?
其實可以這樣理解,其實不管有多少類的對象,虛函數表就這么固定的幾個,是與類的種類個數相同的(所以說相同類所有對象共享的虛函數表),因為是固定的東西,那么在編譯的時候產生就可以了, 而多態的實現是通過對象中的vptr指針指向不同的虛函數表實現的,在運行的時候指針指向是可以有變化的,所以需要在程序運行的時候變化!
#include<stdio.h> #include<iostream> class A{ public:A(); virtual~A(); void fun1(){ printf("123"); } }; A::A(){ printf("new A\n"); } A::~A(){ printf("Delete class A\n"); } class B : public A { public:B(); ~B(); void fun2(){ printf("123456"); } }; B::B(){ printf("new B\n"); } B::~B(){ printf("Delete class B\n"); } class C : public B { public:C(); ~C(); void fun2(){ printf("123456"); } }; C::C(){ printf("new C\n"); } C::~C(){ printf("Delete class C\n"); } int main(){ C tempc; B tempb; A tempa; A *a=&tempc;//指針A在運行是變化,里面相應的虛函數指針也在運行時變化 a=&tempb; a=&tempa; getchar(); return 0; }
總結:虛函數表在編譯的時候就確定了,而類對象的虛函數指針vptr是在運行階段確定的,這是實現多態的關鍵!