多態(tài)的實(shí)現(xiàn)方式 構(gòu)造函數(shù)為什么不可以聲明為虛函數(shù)?
構(gòu)造函數(shù)為什么不可以聲明為虛函數(shù)?前面的回答都很靠譜的提到了重點(diǎn):只有虛函數(shù)才會(huì)出現(xiàn)在虛函數(shù)表里;而且虛函數(shù)表里的項(xiàng)的順序并不保證跟類里虛函數(shù)的聲明順序一致。編譯器實(shí)現(xiàn)和ABI有決定vtable la
構(gòu)造函數(shù)為什么不可以聲明為虛函數(shù)?
前面的回答都很靠譜的提到了重點(diǎn):只有虛函數(shù)才會(huì)出現(xiàn)在虛函數(shù)表里;而且虛函數(shù)表里的項(xiàng)的順序并不保證跟類里虛函數(shù)的聲明順序一致。編譯器實(shí)現(xiàn)和ABI有決定vtable layout的自由。
C 的類的構(gòu)造函數(shù)永遠(yuǎn)不是虛的。它只應(yīng)該在兩種場(chǎng)景使用,
- 在new表達(dá)式中被調(diào)用:new表達(dá)式 = operator new調(diào)用 構(gòu)造函數(shù)調(diào)用。這里總是指定某個(gè)特定的類來new的,整個(gè)行為不會(huì)多態(tài),所以也沒有讓它成為虛函數(shù)的必要性。
- 不過確實(shí)有時(shí)候大家會(huì)希望根據(jù)構(gòu)造的參數(shù)的不同而實(shí)質(zhì)上選擇某個(gè)子類來new。這種需求常常通過工廠函數(shù)(factory function)來解決。
- 被子類的構(gòu)造器的初始化列表調(diào)用。C 里類繼承關(guān)系是靜態(tài)確定的,子類永遠(yuǎn)知道自己的基類是哪些,所以這個(gè)調(diào)用也不可能是虛的。
析構(gòu)函數(shù)則可能是虛的。跟構(gòu)造與析構(gòu)是對(duì)稱的過程,也正因?yàn)槿绱怂砸粋€(gè)不會(huì)為虛而另一個(gè)可能為虛:
- 構(gòu)造:以new表達(dá)式為例,這是從一個(gè)非多態(tài)的信息到一個(gè)可多態(tài)的指針的操作
- 析構(gòu):以delete表達(dá)式為例,這是一個(gè)從可多態(tài)的指針要找到具體類型信息的操作
===========================================
至于如何在程序里找出構(gòu)造函數(shù)和析構(gòu)函數(shù)的地址。構(gòu)造函數(shù)的地址是肯定不會(huì)出現(xiàn)在vtable里的了。那咋搞?
題主給問題打上了逆向工程的標(biāo)簽,而且看來環(huán)境是MSVC,那如果目標(biāo)文件里還有符號(hào)表的話,其實(shí)最直觀的辦法就是去符號(hào)表里把構(gòu)造函數(shù)的decorated name對(duì)應(yīng)的地址項(xiàng)找出來。具體咋操作還得看題主到底是在什么條件下需要找出這個(gè)地址來做什么。
為什么構(gòu)造函數(shù)不能是虛函數(shù)?
構(gòu)造函數(shù)不能聲明為虛函數(shù)的原因是:所謂虛函數(shù)就是多態(tài)情況下只執(zhí)行一個(gè),而從繼承的概念來講,總是要先構(gòu)造父類對(duì)象,然后才能是子類對(duì)象,如果構(gòu)造函數(shù)設(shè)為虛函數(shù),那么當(dāng)你在構(gòu)造父類的構(gòu)造函數(shù)時(shí)就不得不顯示的調(diào)用構(gòu)造,還有一個(gè)原因就是為了防錯(cuò),試想如果你在子類中一不小心重寫了個(gè)跟父類構(gòu)造函數(shù)一樣的函數(shù),那么你的父類的構(gòu)造函數(shù)將被覆蓋,也即不能完成父類的構(gòu)造.就會(huì)出錯(cuò).------子類繼承了父類的public方法以后,當(dāng)然可以在public中添加新的方法和屬性(屬性一般放在private或者protect里面),這是繼承的基本用法哦
為何構(gòu)造函數(shù)不能成為虛函數(shù)?
構(gòu)造函數(shù)的左右就是初始化變量等的值, VC 的語(yǔ)法是,只要用戶定義了構(gòu)造函數(shù),系統(tǒng)就不會(huì)提供任何構(gòu)造函數(shù) 如果將他定義成虛函數(shù),程序初始的時(shí)候不能初始化變量,不能申請(qǐng)內(nèi)存空間,程序會(huì)無法運(yùn)行