您好,登錄后才能下訂單哦!
C++中的虛成員函數和動態聯編是什么?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
虛成員函數:
虛函數允許派生類取代基類所提供的實現。編譯器確保當對象為派生類時,取代者(譯注:即派生類的實現)總是被調用,即使對象是使用基類指針訪問而不是派生類的指針。這樣就允許基類的算法被派生類取代,即使用戶不知道派生類的細節。
派生類可以完全地取代基類成員函數(覆蓋(override)),也可以部分地取代基類成員函數(增大(augment))。如果愿意的話,后者由派生類成員函數調用基類成員函數來完成。
在構造函數訪問順序中,一般來說是先訪問父類的構造函數再訪問子類的構造函數,析構函數則是先訪問子類的析構函數,再訪問父類的析構函數。
動態聯編:
編譯程序在編譯階段并不能確切知道將要調用的函數,只有在程序運行時才能確定將要調用的函數,為此要確切知道該調用的函數,要求聯編工作要在程序運行時進行,這種在程序運行時進行聯編工作被稱為動態聯編。動態聯編又稱動態關聯。
編譯器對非虛方法使用靜態聯編(編譯時匹配),對虛方法使用動態聯編(運行時匹配)。
靜態聯編比動態聯編效率高。
虛函數的工作原理。
虛函數。
重新定義成員函數(改變函數特征標)。
重新定義重載的成員函數。
效率
為使程序能夠在運行階段進行決策,必須采取一些方法來跟蹤基類指針或引用指向的對象類型,這增加了額外的處理開銷。因此下列情況更適合靜態聯編:
因此靜態聯編被設置為C++的默認選擇。
如果要在派生類中重新定義基類的方法,則將它設置為虛方法;否則設置為非虛方法。
虛函數的工作原理
編譯器處理虛函數的方法是:給每個對象添加一個隱藏成員。隱藏成員中保存了一個指向·函數地址·數組的指針。這種數組被稱為虛函數表(vtbl),表中存儲了為類對象進行聲明的虛函數的地址。
派生類對象將包含一個指向獨立地址表的指針(即新創建一個表)。(增加內存開銷)
調用虛函數時,程序將查看存儲在對象中的vtbl地址,然后轉向相應的函數地址表并在表中查找地址。(影響執行速度)
總之,使用虛函數將在內存和執行速度上有一定的成本;即使非函數的效率比虛函數稍高,卻不具備動態聯編功能。
構造函數不能是虛函數。
析構函數應當是虛函數,除非類不用做基類。
友元函數不能是虛函數,因為友元不是類成員,而只有成員才可以是虛函數。
如果派生類沒有重新定義函數,將使用該函數的基類版本(繼承它)。如果派生類位于派生鏈中,則將使用最新的虛函數版本(指針或引用調用),基類版本被隱藏的情況除外。
重新定義將隱藏基類方法:
class Dwelling {public: virtual void showperks(int a) const; ... };class Hovel : public Dwelling {public: virtual void showperks() const; ... }
在派生類中重新定義函數(改變了參數特征標),將隱藏同名的基類方法,而不是重載基類方法。
Hovel trump; trump.showperks(); // validtrump.showperks(5); // invalid
如果重新定義繼承的方法,應確保與原來的原型完全相同。如果返回類型為基類引用或指針,則可以修改為指向派生類的引用或指針(返回類型協變:即允許返回類型隨類類型的變化而變化)。
如果基類聲明被重載了,則應在派生類中重新定義所有的基類版本;如果只定義了一個版本,則其它版本將被隱藏,派生類對象將無法使用它們。
class Dwelling {public: virtual void showperks(int a) const; virtual void showperks(double x) const; virtual void showperks() const; ... };class Hovel : public Dwelling { virtual void showperks(int a) const; virtual void showperks(double x) const; virtual void showperks() const; ... };
如果不需要修改,則新定義可只調用基類版本:
void Hovel::showperks()const {Dwelling::showperks();}
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。