今天通過對實驗二繼承,過載,覆蓋的學習,讓我更深一步理解了這些概念的區別。
首先來明確乙個概念,函式名即位址,也就是說函式名就是個指標。
編譯階段,編譯器為每個函式的**分配乙個位址空間並編譯函式**到這個空間中,函式名就指向這個位址空間。
也即每個函式名都有自己唯一的**空間。
同理,類的成員函式也是如此。
但是,有一點大家一定要記住,c++編譯器編譯cpp檔案時,會根據"c++編譯器的函式名修飾規則" 對函式名進行修飾。
(修飾規則大家自己去搜吧,我就不敘述了),前面講到函式名稱的作用是指向函式真實**的指標。
知道了以上規則,那麼我們對函式覆蓋便不難理解了。
我們來寫一段函式覆蓋的**
class father
此時有些人可能就不能理解為什麼會出現這種呼叫結果了,那麼大家是否還記得我上面曾提到的"c++編譯器的函式名修飾規則"?
我們來根據"c++編譯器的函式名修飾規則"再來想想原因。
根據規則,編譯器把父類father中的fun函式名編譯為"?fun@father@@qaez",子類son中的fun函式名編譯為"?fun@son@@qaez"。
當pson->fun();呼叫時,編譯器會把pson所存位址值的型別轉化成當前指標型別,而pson的當前型別為son(這句話不多餘,
因為型別是可以隨意轉換的),
所以表示式"pson->fun()"全部展開以後得到的函式名稱即"?fun@father@@qaez"
同理表示式"pfather->fun()"全部展開以後得到的函式名稱即"?fun@son@@qaez",
既然得出了函式名,那麼也就可以根據函式名稱,跳轉到真實的函式**實體位置了。
根據以上分析,我覺得"函式覆蓋(英文名不知到叫什麼只能用中文了)"這個詞彙真的容易把人帶入歧途,
我的語文又不好,所以還希望哪位語文好的兄弟,來重新翻譯下"函式覆蓋"這個詞彙。
呃,真費勁啊,函式覆蓋算是講完,不知道大家有每有看懂,如果還看不懂的話,我是真沒招了。
下面在來講個虛函式吧。
有了前面的基礎,大家應該對函式有了充分的了解。
那麼問大家乙個問題,為什麼乙個類實力化後普通成員函式不影響例項的大小?
呵呵,如果乙個新手能回答出來,那我這篇東西就不算白寫。
正確答案嘛,是因為不需要它來影響例項大小,因為編譯器會根據"c++編譯器的函式名修飾規則"與"表示式的位址型別",
自動的把成員函式展開成完整的函式名,也就找到了函式的真實位址,所以普通成員函式是不影響實力大小的。
我再來問大家乙個問題,你們認為虛函式需不需要影響類的例項大小?
哈哈,這次的答案是需要。
這次我們來寫一段虛函式的**瞧瞧 因為只有在例項內部新增乙個指標,才能夠完成例如,
class father
恩,大家需要調式一下上面的程式,對father新增監視,你會發現father例項中莫名其妙的多了乙個vftable型別指標物件vfptr。
是了,虛函式的實現靠的就是這個東西了。
ied幫我們在我們的例項外部例項化了乙個vftable物件(我知道這句話很繞,但是我不知道該怎麼更好的解釋了),
同時為我們的例項father新增了乙個指向vftable物件的指標vfptr。
我們繼續把監視中的指標vfptr展開,可以看到乙個叫[0]的函式指標(別問我這名為啥長成這樣,我也沒搞清楚),
哈哈,找到了,這裡儲存了乙個位址,這個位址就是乙個函式真實位址(如果用的vs2010編譯器,你會直觀的看到這個位址
所對應的是father::fun這個函式)。
然後,我再來明確乙個虛函式規則,就是當你的例項呼叫虛函式時,最終呼叫的就是這個vftable型別的成員[0]所儲存位址。
那麼好了,我們知道子類是完全繼承父類的,所以那個vftable型別指標物件vfptr也同時被繼承了下來。
ide同樣為我們例項化乙個vftable物件,讓vfptr來指向這個vftable物件。
而如果我們的子類重寫了虛函式,那麼ide在例項化vftable物件時,就會把[0]這個指標重寫為新的子類中那個虛函式位址。
如果我們的子類沒有重寫這個虛函式,那麼ide就會找到距離這個子類關係最近的乙個實現了虛函式的父類,
把這個父類中的虛函式位址,寫入到子類的[0]中。
這樣子類在呼叫虛函式的時候,就可以實現動態繫結了。
另外父類指標指向子類例項時,因為有了vfptr指標佔位,所以當父類指標呼叫虛函式時,定址到的vfptr是子類例項的。
而子類的vfptr指向子類自己的vftable物件,所以父類最終呼叫的會是子類物件的中[0],所以[0]中存的是哪個函式位址。
父類指標最終呼叫的就會是哪個函式了。
c 繼承覆蓋與函式過載
函式過載的機制 在c中函式名是具有唯一性的,但是在c 中函式名可以相同。c c 編譯器在實現函式名轉換過程中的機制不同。void get int num 在gcc下 在g 下 從上述比較中可以看出,c 函式名相同時,只要引數不同,底層就會解釋為不同的函式名 在c 中使用c函式或者庫時,需要新增 ex...
C 的過載 覆蓋 隱藏 繼承
函式過載 函式的繼承 這個不多說 子類繼承父類的公有變數 函式的覆蓋 也是重寫 關於子類修改了父類的成員函式 所以呼叫跟父類同名的成員函式 顯示的是子類的修改的函式的輸出方式 函式的隱藏 在父類和子類都有同名函式時,可以是顯示父類的函式輸出方式 也可以是顯示子類的輸出方式 但兩者會顯示的原因不同,如...
C 繼承之 過載 覆蓋 隱藏
在c 繼承中經常會遇到函式過載 覆蓋 隱藏這三個玩意,但是這三者的本質區別又是什麼,自己在網上和資料里查後並通過 證實,下面我們看看者三者的本質 1 過載 過載是c 獨有的乙個特性,c下面是沒有的,具體分析請看 這裡我們來具體看看過載,過載特點 1 在同一範圍 2 函式名相同 3 引數不同 4 返回...