C++知識點隨筆(四):耦合問題、new和malloc、虛析構、多繼承

吃不夠的圓兒寶發表於2015-07-08

一、耦合問題

即互相包含標頭檔案的問題,解決方法:
1. 在一個類的標頭檔案裡宣告另一個類,那麼我們在定義的時候就不能new物件,但是可以定義一個指標。這只是為了保證編譯通過,等到具體建立物件的時候還是會使用原來的類成員。
2. 可以抽象出一個父類,讓這個父類裡面同時包含這兩個子類裡需要耦合的部分。
3. friend方法,其實也相當於一個宣告,但是friend會破壞類的封裝性。(傳說中友元是不需要標頭檔案的)。
4. 降低耦合性參考:http://developer.178.com/200912/54167815997.html

二、new和malloc的區別

malloc只是在堆區申請空間;
而new裡面封裝了三件事情:
1. 呼叫類的建構函式
2. 在堆區申請空間
3. 返回物件的首地址

delete封裝了兩件事:
1. 呼叫解構函式
2. 刪除指標所指向的全部空間
注意:delete刪除空間時一定將new的物件大小全部刪除了,但是呼叫誰的析構就要看這個指標本身的型別了。所以當這種情況時:

CFather *son = new CSon;
delete son;

就不會呼叫子類的解構函式,從而可能會造成記憶體洩露。所以要解決這個問題,就有了我們後面的虛析構的誕生。

三、虛析構

虛析構就是當我們delete父類指標的時候,會首先呼叫子類的解構函式,然後再呼叫父類的解構函式,這樣就保證了所有的子類解構函式都可以呼叫,從而避免了記憶體洩露的問題。它的形式是這樣的:

virtual ~CFather();

什麼時候用虛析構呢?
有多型或者說有virtual的時候就用虛析構。這個虛析構同樣也存在於虛擬函式列表中,子類的解構函式會重寫這個表中的虛解構函式指標。注意:虛解構函式指標不一定就在虛擬函式列表的最後,它和普通虛擬函式一樣,是根據父類中宣告的順序加入虛擬函式列表的。

為什麼呼叫子類的解構函式之後一定會呼叫父類的解構函式?
我們之前講過,子類繼承父類的過程其實相當於在最開始的時候定義了一個父類的物件,那麼當我們執行完子類的解構函式之後,這個子類就要回收了,所以定義的父類的物件的作用域也就結束了,就會自動呼叫父類物件的解構函式了。

四、多繼承

多繼承形式:

class AA : public BB, public CC

多繼承的構造順序是:BB->CC->AA
多繼承的所以父類中,從左向右依次執行建構函式。
多繼承的缺點:
多繼承會出現訪問不明確的問題,因為多繼承是這樣的:
這裡寫圖片描述
所以有兩份AA,這樣我們在使用AA的成員變數的時候就會發生訪問不明確的問題,解決的方法就是使用虛繼承,這個我們後面再講。
另外當我們多繼承的父類,即BB和CC同時擁有兩個同名的虛擬函式時,子類也無法將他們重寫,還是指向不明確的問題,這個問題我們可以通過巢狀類來解決,後面再講。
其實多繼承的出現本身就是一種缺陷,證明了我們的程式設計的不夠完美,所以我們在程式設計的時候儘量避免多繼承的出現。

相關文章