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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

C++中的虚函数与纯虚函数

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

文章目錄

    • 1 C++中的虛函數
      • 1.1 虛函數
      • 1.2 單個類的虛函數表
      • 1.3 使用繼承的虛函數表
      • 1.4 多重繼承的虛函數表
    • 2 C++中的純虛函數

1 C++中的虛函數

1.1 虛函數

虛函數的定義:

  • 在函數的返回類型之前使用virtual。
  • 只在成員函數的聲明中添加virtual, 在成員函數的實現中不要加virtual。

虛函數的繼承:

  • 如果某個成員函數被聲明為虛函數,那么它的子類【派生類】,以及子類的子類中,所繼承的這個成員函數,也自動是虛函數。
  • 如果在子類中重寫這個虛函數,可以不用再寫virtual, 但是仍建議寫virtual, 更可讀!

C++中通過虛函數實現多態。

1.2 單個類的虛函數表

代碼如下:

#include <iostream> using namespace std;class Father { public:virtual void func1() { cout << "Father::func1" << endl; }virtual void func2() { cout << "Father::func2" << endl; }virtual void func3() { cout << "Father::func3" << endl; }void func4() { cout << "非虛函數:Father::func4" << endl; } public: //為了便于測試,特別該用publicint x = 100;int y = 200;static int z; };typedef void (*func_t)(void); int Father::z = 1; int main(void) {Father father;// 含有虛函數的對象的內存中,最先存儲的就是“虛函數表”cout << "對象地址:" << (int*)&father << endl;int* vptr = (int*)*(int*)&father;cout << "虛函數表指針vptr:" << vptr << endl;cout << "調用第1個虛函數: ";((func_t) * (vptr + 0))();cout << "調用第2個虛函數:";((func_t) * (vptr + 1))();cout << "調用第3個虛函數: ";((func_t) * (vptr + 2))();cout << "第1個數據成員的地址: " << endl;cout << &father.x << endl;cout << std::hex << (int)&father + 4 << endl;cout << "第1個數據成員的值:" << endl;cout << std::dec << father.x << endl;cout << *(int*)((int)&father + 4) << endl;cout << "第2個數據成員的地址: " << endl;cout << &father.y << endl;cout << std::hex << (int)&father + 8 << endl;cout << "第2個數據成員的值:" << endl;cout << std::dec << father.y << endl;cout << *(int*)((int)&father + 8) << endl;cout << "sizeof(father)==" << sizeof(father) << endl;Father father2;cout << "father的虛函數表:";cout << *(int*)(*(int*)&father) << endl;cout << "father2的虛函數表:";cout << *(int*)(*(int*)&father2) << endl;system("pause");return 0; }

執行效果:

VS的對象內存分布分析:
項目的命令行配置中添加: /d1 reportSingleClassLayoutFather


手繪內存分布:

結果分析:

  • 對象內,首先存儲的是“虛函數表指針”,又稱“虛表指針”。然后再存儲非靜態數據成員。
  • 對象的非虛函數,保存在類的代碼中!
  • 對象的內存,只存儲虛函數表和數據成員(類的靜態數據成員,保存在數據區中,和對象是分開存儲的)。
  • 添加虛函數后,對象的內存空間不變!僅虛函數表中添加條目。多個對象,共享同一個虛函數表!

1.3 使用繼承的虛函數表

首先看如下示例代碼:

#include <iostream> using namespace std;class Father { public:virtual void func1() { cout << "Father::func1" << endl; }virtual void func2() { cout << "Father::func2" << endl; }virtual void func3() { cout << "Father::func3" << endl; }void func4() { cout << "非虛函數:Father::func4" << endl; } public: //為了便于測試,特別該用publicint x = 100;int y = 200; };class Son : public Father { public:void func1() { cout << "Son::func1" << endl; }virtual void func5() { cout << "Son::func5" << endl; } };typedef void (*func_t)(void);int main(void) {Father father;Son son;// 含有虛函數的對象的內存中,最先存儲的就是“虛函數表”cout << "son對象地址:" << (int*)&son << endl;int* vptr = (int*)*(int*)&son;cout << "虛函數表指針vptr:" << vptr << endl;for (int i = 0; i < 4; i++) {cout << "調用第" << i + 1 << "個虛函數:";((func_t) * (vptr + i))();}for (int i = 0; i < 2; i++) {// +4 是因為先存儲了虛表指針cout << *(int*)((int)&son + 4 + i * 4) << endl;}system("pause");return 0; }

執行效果:

內存分布:

子類虛函數表的構建過程:

1.4 多重繼承的虛函數表

代碼如下:

#include <iostream>using namespace std;class Father { public:virtual void func1() { cout << "Father::func1" << endl; }virtual void func2() { cout << "Father::func2" << endl; }virtual void func3() { cout << "Father::func3" << endl; }void func4() { cout << "非虛函數:Father::func4" << endl; } public:int x = 200;int y = 300;static int z; };class Mother { public:virtual void handle1() { cout << "Mother::handle1" << endl; }virtual void handle2() { cout << "Mother::handle2" << endl; }virtual void handle3() { cout << "Mother::handle3" << endl; } public: //為了便于測試,使用public權限int m = 400;int n = 500; };class Son : public Father, public Mother { public:void func1() { cout << "Son::func1" << endl; }virtual void handle1() { cout << "Son::handle1" << endl; }virtual void func5() { cout << "Son::func5" << endl; } };int Father::z = 0;typedef void(*func_t)(void);int main(void) {Son son;int* vptr = (int*) * (int*)&son;cout << "第一個虛函數表指針:" << vptr << endl;for (int i = 0; i < 4; i++) {cout << "調用第" << i + 1 << "個虛函數:";((func_t) * (vptr + i))();}for (int i = 0; i < 2; i++) {cout << *(int*)((int)&son + 4 + i * 4) << endl;}int* vptr2 = (int*) * ((int*)&son + 3);for (int i = 0; i < 3; i++) {cout << "調用第" << i + 1 << "個虛函數:";((func_t) * (vptr2 + i))();}for (int i = 0; i < 2; i++) {cout << *(int*)((int)&son + 16 + i * 4) << endl;}system("pause");return 0; }

執行結果:

VS分析:

內存分布:


2 C++中的純虛函數

純虛函數是指只定義原型的成員函數。一個C++類中存在純虛函數就成為了抽象類。

純虛函數的語法規則:

能夠將父類的析構函數聲明為純虛函數?
可以的,當我們將符類的析構函數聲明為純虛時,仍然需要給出父類析構函數的實現,否則鏈接報錯。此時父類仍然是抽象類,由于有了虛函數,就可以實現多態,使用父類指針釋放空間時可以正確的調用析構函數。


參考資料:

  • C/C++從入門到精通-高級程序員之路【奇牛學院】
  • 總結

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

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