今天通過對實驗二繼承,過載,覆蓋的學習,讓我更深一步理解了這些概念的區別。
首先來明確乙個概念,函式名即位址,也就是說函式名就是個指標。
編譯階段,編譯器為每個函式的**分配乙個位址空間並編譯函式**到這個空間中,函式名就指向這個位址空間。
也即每個函式名都有自己唯一的**空間。
同理,類的成員函式也是如此。
但是,有一點大家一定要記住,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 學習之繼承篇(多重繼承之虛繼承)
虛繼承 是物件導向程式設計中的一種技術,是指乙個指定的基類,在繼承體系結構中,將其成員資料例項共享給也從這個基型別直接或間接派生的其它類。形式 在繼承定義中包含了virtual關鍵字的繼承關係,如下圖中,類a就叫做虛基類。虛擬繼承是多重繼承中的菱形繼承所特有的概念。虛擬基類是為解決多重繼承而出現的。...
C 之繼承篇
c 繼承篇 1 基本概念 繼承 inheritance 機制是物件導向程式設計使 可以復用的最重要的手段,它允許程式設計師在保持 原有類特性的基礎上進行擴充套件,增加功能。這樣產生新的類,稱派生類。繼承呈現了物件導向程式設 計的層次結構,體現了由簡單到複雜的認知過程。2 繼承格式及特性 class ...
C 之繼承篇
1.繼承許可權 繼承許可權與訪問許可權 public 公有訪問 protected 保護訪問 private 私有訪問 public 公有繼承 繼承後變成public 公有訪問 繼承後變成protected 保護訪問 繼承後不可訪問 protected 保護繼承 繼承後變成protected 保護訪...