c++虛函數

說到虛函數,首先要講一下OOP中的多態多態簡單的說就是一個接口,多種實現.

多態分為編譯時多態運行時多態
編譯時多態主要體現在函數重載;
運行時多態是指程序在運行時動態地識別對象,實現不同的行為,這是通過虛函數+繼承實現的。

虛函數必須是類的非靜態成員函數,也不能是構造函數, 訪問權限為public, 雖然在語法上設置成 privateprotect 并沒有錯誤,但虛函數的目的是為了實現多態,所以設置成 protectprivate 是沒有意義的。

靜態成員函數不能是 virtual 函數的原因

  • 靜態成員函數可以不通過對象來調用,靜態成員函數沒有隱藏的this指針;virtual函數只能通過對象來調用,實現需要依靠隱藏的this指針
  • 靜態成員函數是在編譯時就綁定了,而virtual函數在運行時才進行綁定

構造函數不能是 virtual 函數的原因

  • 首先從設計理念上來說,構造函數不需要設置成 virtual 函數,從實現機制來說,構造函數也無法實現 virtual 函數
  • 構造函數顧名思義就是構建一個對象,而虛函數是動態的識別對象的類型,這個對象屬于是基類、派生類還是更深層次的類,這是運行在對象已經存在的基礎上的。所以虛函數的調用必須在構造函數調用之后
  • 虛函數的執行依賴于虛函數指針 vptr, 而 vptr 的初始化即讓 vptr 指向 虛函數表 V-table 是在構造函數中實現的,所以
    構造函數不能是虛函數

虛函數表 vtable 和虛函數表指針 vptr

C++的虛函數的實現機制依靠的就是 vtablevptr
vtable 實際上就是 virtual 函數的地址表,這張表解決了繼承和覆蓋的問題
例如:

class A {
public:
        virtual void f();
        virtual void g();
};
class B: public A{
 public:
          virtual void f();
          virtual void h();
};
B::f() A::g() B::h() 0

上面表格則為B的 vtable, 最后一個值如果為1說明還有下一個虛函數表,存在于多重繼承的情況下。
B類的內存分布的第一項即是 vptr,該指針指向B的 vtable

注意:

vtable 在編譯時期確立, vptr 在運行期確立。

在繼承中析構函數一定要被設置成虛函數

如果不設置成虛函數,那么當父類的指針調用子類的對象,該指針調用析構函數,將會調用父類的析構函數,而子類多出的那一部分數據內存將無法被釋放。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • C++虛函數 C++虛函數是多態性實現的重要方式,當某個虛函數通過指針或者引用調用時,編譯器產生的代碼直到運行時才...
    小白將閱讀 1,756評論 4 19
  • 什么是繼承?什么是多重繼承?多重繼承存在變量和函數名沖突怎么辦?子類對象和父類對象的內存模型是什么樣的?虛繼承如何...
    金戈大王閱讀 2,658評論 3 12
  • 參考來源:知乎 定義一個函數為虛函數,不代表函數為不被實現的函數。定義他為虛函數是為了允許用基類的指針來調用子類的...
    夜幕青雨閱讀 859評論 0 6
  • 今天是哥哥選擇離開這個世界是日子,過去了這么多年,他的真依然留在我們的心中。 對于哥哥的離開,大多數的人都只是關注...
    知更鳥Robin閱讀 317評論 0 0
  • 這個世界上好看的臉蛋太多,有趣的靈魂太少。 ——王爾德 今天媽媽發微信圖片給我,圖片是一株顏值有點低,有點丑但是看...
    愛吃肉的小仙女閱讀 706評論 0 2