日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++的虚函数表

發布時間:2023/12/20 c/c++ 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++的虚函数表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這里的例子全部來自陳皓的C++ 虛函數表解析,經過修改的。

編譯器:g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2

環境:ubuntu 15.04 ?64位系統(地址占8字節)

?

例子1:

1 #define LL long long 2 3 class Base { 4 public: 5 virtual void f() { cout << "Base::f" << endl; } 6 virtual void g() { cout << "Base::g" << endl; } 7 virtual void h() { cout << "Base::h" << endl; } 8 LL a; 9 }; 10 11 int main(void) 12 { 13 typedef void (*Fun)(void); 14 Base b; 15 b.a=10086; 16 17 Fun pFun = NULL; 18 19 cout << "虛函數表地址:" << (int*)(&b) << endl; 20 cout << "虛函數表 — 第一個函數地址:" << (int*)*(int*)(&b) << endl; 21 22 LL *p=(LL*)*(LL*)&b; 23 for(int i=0; i<3; i++) 24 { 25 pFun = (Fun)*(p+i); 26 pFun(); 27 } 28 cout<<"a的地址: "<<(&b)+1<<endl; 29 cout<<"a的值: "<<*((LL*)(&b)+1)<<endl; 30 cout<<"對象b的大小:"<<sizeof(b)<<endl; 31 32 return 0; 33 }

輸出:

?

  解釋:通過強轉對象b的地址,將地址逐個取出來運行看看是什么。

  總結:對象b中存儲了2個東西,第一個是虛函數表指針,第二個是變量a,所以共計8+8=16字節。在虛函數表指針所指的地址中,有3個指針,分別是3個虛函數的指針,每個占8字節,共計3*8=24字節。陳皓說虛表最后加個標志,這點不知道怎么驗證~

  驗證了如下這副圖:

  

?

?

?

例子2:

  一般繼承,無函數覆蓋的,全部函數都聲明為virtual:  

  

1 class Base { 2 public: 3 virtual void f() { cout << "Base::f" << endl; } 4 virtual void g() { cout << "Base::g" << endl; } 5 virtual void h() { cout << "Base::h" << endl; } 6 }; 7 8 class Derive:public Base{ 9 public: 10 virtual void f1() { cout << "Derive::f1" << endl; } 11 virtual void g1() { cout << "Derive::g1" << endl; } 12 virtual void h1() { cout << "Derive::h1" << endl; } 13 }; 14 15 int main(void) 16 { 17 typedef void (*Fun)(void); 18 Derive d; 19 Fun pFun = NULL; 20 21 cout << "虛函數表地址:" << (LL*)(&d) << endl; 22 cout << "虛函數表 — 第一個函數地址:" << (LL*)*(LL*)(&d) << endl; 23 24 LL *p=(LL*)*(LL*)&d; 25 for(int i=0; i<6; i++) 26 { 27 pFun = (Fun)*(p+i); 28 pFun(); 29 } 30 cout<<"對象d的大小:"<<sizeof(d)<<endl; 31 32 return 0; 33 }

輸出:

  解釋:僅僅只有2個類,且Derive繼承Base類,一共有6個虛函數。

  總結:對象d中一共占用8個字節,也就是只保存了虛函數表的地址。虛函數表中一共有6個函數指針,分別是Base的3個+Derive的3個。

  驗證了如下這副圖:

  

?

例子3:

  一般繼承,只有1個函數是覆蓋的,全部函數都聲明為virtual:
  

1 class Base { 2 public: 3 virtual void f() { cout << "Base::f" << endl; } 4 virtual void g() { cout << "Base::g" << endl; } 5 virtual void h() { cout << "Base::h" << endl; } 6 }; 7 8 class Derive:public Base{ 9 public: 10 virtual void f() { cout << "Derive::f" << endl; } 11 virtual void g1() { cout << "Derive::g1" << endl; } 12 virtual void h1() { cout << "Derive::h1" << endl; } 13 }; 14 15 int main(void) 16 { 17 typedef void (*Fun)(void); 18 Derive d; 19 Fun pFun = NULL; 20 21 cout << "虛函數表地址:" << (LL*)(&d) << endl; 22 cout << "虛函數表 — 第一個函數地址:" << (LL*)*(LL*)(&d) << endl; 23 24 LL *p=(LL*)*(LL*)&d; 25 for(int i=0; i<5; i++) 26 { 27 pFun = (Fun)*(p+i); 28 pFun(); 29 } 30 31 cout<<"對象d的大小:"<<sizeof(d)<<endl; 32 33 return 0; 34 }

輸出:

  解釋:這個模型跟上面的差不多,而這次有1個函數是覆蓋的。

  總結:虛函數表中一共有5個函數指針,Base中占2個,Derive中占3個。流程是先將基類的3個函數擺在虛函數表前面,接著擺派生類的,由于Derive的函數f覆蓋掉基類Base的函數f,所以直接代替基類的函數f的位置。多態是:用基類的指針指向派生類對象,調用的是有覆蓋的派生類中的函數。這里就可以實現多態~

  驗證了如下這副圖:

  

?

?

例子4:

  多重繼承,無虛函數覆蓋,但全部函數都聲明為虛函數。

  ?

1 class Base1 { 2 public: 3 virtual void f() { cout << "Base1::f" << endl; } 4 virtual void g() { cout << "Base1::g" << endl; } 5 virtual void h() { cout << "Base1::h" << endl; } 6 }; 7 class Base2 { 8 public: 9 virtual void f() { cout << "Base2::f" << endl; } 10 virtual void g() { cout << "Base2::g" << endl; } 11 virtual void h() { cout << "Base2::h" << endl; } 12 }; 13 class Base3 { 14 public: 15 virtual void f() { cout << "Base3::f" << endl; } 16 virtual void g() { cout << "Base3::g" << endl; } 17 virtual void h() { cout << "Base3::h" << endl; } 18 }; 19 20 class Derive:public Base1,public Base2,public Base3{ 21 public: 22 virtual void f1() { cout << "Derive::f1" << endl; } 23 virtual void g1() { cout << "Derive::g1" << endl; } 24 }; 25 26 int main(void) 27 { 28 typedef void (*Fun)(void); 29 Derive d; 30 Fun pFun = NULL; 31 32 cout << "虛函數表地址:" << (LL*)(&d) << endl; 33 cout << "虛函數表 — 第一個函數地址:" << (LL*)*(LL*)(&d) << endl; 34 35 LL *p=(LL*)*(LL*)&d; 36 for(int i=0; i<5; i++) 37 { 38 pFun = (Fun)*(p+i); 39 pFun(); 40 } 41 for(int i=0; i<3; i++) 42 { 43 pFun = (Fun)*(p+i); 44 pFun(); 45 } 46 for(int i=0; i<3; i++) 47 { 48 pFun = (Fun)*(p+i); 49 pFun(); 50 } 51 52 cout<<"對象d的大小:"<<sizeof(d)<<endl; 53 54 return 0; 55 }

輸出:

  解釋:Derive類一共有3個基類,按1,2,3的順序繼承。由于有3個基類,所以對象d中有且僅有3個指針,分別指向其基類的虛函數表。

  總結:虛函數表1中有5個函數,虛函數表2和3中有3個函數。也就是說,基類Derive中的虛函數是借放在第一個基類的虛函數表中的尾部。

  驗證了如下這副圖:

  

?

例子5:

  多重繼承,有1個虛函數覆蓋,全部函數聲明為虛函數。

  

1 class Base1 { 2 public: 3 virtual void f() { cout << "Base1::f" << endl; } 4 virtual void g() { cout << "Base1::g" << endl; } 5 virtual void h() { cout << "Base1::h" << endl; } 6 }; 7 class Base2 { 8 public: 9 virtual void f() { cout << "Base2::f" << endl; } 10 virtual void g() { cout << "Base2::g" << endl; } 11 virtual void h() { cout << "Base2::h" << endl; } 12 }; 13 class Base3 { 14 public: 15 virtual void f() { cout << "Base3::f" << endl; } 16 virtual void g() { cout << "Base3::g" << endl; } 17 virtual void h() { cout << "Base3::h" << endl; } 18 }; 19 20 class Derive:public Base1,public Base2,public Base3{ 21 public: 22 virtual void f() { cout << "Derive::f" << endl; } 23 virtual void g1() { cout << "Derive::g1" << endl; } 24 }; 25 26 27 28 int main(void) 29 { 30 typedef void (*Fun)(void); 31 Derive d; 32 Fun pFun = NULL; 33 34 cout << "虛函數表地址:" << (LL*)(&d) << endl; 35 cout << "虛函數表 — 第一個函數地址:" << (LL*)*(LL*)(&d) << endl; 36 37 LL *p=(LL*)*(LL*)&d; 38 for(int i=0; i<4; i++) 39 { 40 pFun = (Fun)*(p+i); 41 pFun(); 42 } 43 for(int i=0; i<3; i++) 44 { 45 pFun = (Fun)*(p+i); 46 pFun(); 47 } 48 for(int i=0; i<3; i++) 49 { 50 pFun = (Fun)*(p+i); 51 pFun(); 52 } 53 54 cout<<"對象d的大小:"<<sizeof(d)<<endl; 55 56 return 0; 57 }

輸出:

  解釋:例子基本和上一個例子一樣。基類Derive中的虛函數f 覆蓋掉3個基類中的同名虛函數f。

  總結:依然是3個函數表,只是每個函數表中的同名函數f 都被替換成了基類Derive中的函數f 。所以虛函數表1中有4個指針,表2和3都分別有3個。

?

轉載于:https://www.cnblogs.com/xcw0754/p/4973532.html

總結

以上是生活随笔為你收集整理的C++的虚函数表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。