c 繼承機制易犯的錯誤

2021-06-09 15:21:28 字數 1460 閱讀 7269

繼承作為物件導向的基本特徵之一,其使用率極高。不管是為了實現軟體的基本功能,還是再程式的重構的過程中,我們總是會用到繼承機制。正是因為其用途極為廣泛,而且使用簡單,大眾程式設計師對其真正的內部實現機制的**不是很深。而且,在大部分情況下,我們對繼承的使用方法是錯誤的。下面用例子來說明問題。

class animal ;

class animal1: public animal ;

class animal2: public animal ;

上面的**只是簡單的定義乙個繼承體系,即animal作為基類,animal1和animal2公共繼承它。三者都過載了賦值運算子。這對於問題的說明已經足夠了。考慮下面的**:

animal1 an1;

animal2 an2;

animal *pan1 = &an1;

animal *pan2 = &an2;

...*pan1 = *pan2;

上面的**足夠簡單了吧!問題就出現了。我們在最後一行的目的是將an2賦值給an1.如果你不是此目的,那麼可以繞開本文了!因為通過指標,對物件進行賦值動作對於c++程式設計師來說,非常普遍。但是實際的效果確是,an1的animal成分與an2的animal成分相同,而an1的animal1成本保持不變。這裡提一下出現這種情況的原因:1.繼承體系中的賦值函式是過載,而不是覆蓋和隱藏(注意三者的區別:);2.由於animal *pan1 = &an1,是產生pan1所覆蓋的範圍縮小的效果,因此當採用賦值操作時,實際上呼叫的賦值函式時基類的賦值函式。這種效果是不是導致你的an1物件二不象了,既不是原來的an1物件,也不是你期待的an2物件。不過,如果你是想達到這種移花接木的效果,那麼我恭喜你,這種用法太妙了,也說明你對c++ 的繼承體系已經到了一種登峰造極的地步。

不過,大部分人都不是實現移花接木的功能,那麼怎麼實現全部成分的賦值效果呢?

既然已經用到了繼承機制,那麼就不得離開虛函式了。我們將賦值操作符函式定義為虛函式,**如下:

class animal ;

class animal1: public animal ;class animal2: public animal ;

採用虛函式確實能夠解決上面提到的全部成分的賦值效果,因為他會導致覆蓋賦值函式,而不是上面的過載,因此會呼叫實際animal1類的賦值函式。但這樣仍然會帶來問題,如下的**:

animal1 an1;

animal2 an2;//這裡是animal2物件,與前面的animal1不同

animal *pan1 = &an1;

animal *pan2 = &an2;

...*pan1 = *pan2;//將animal2物件賦值給animal1

這樣子會允許異型轉換,明顯還是會出現問題。如何解決呢?可以參考《more effective c++》裡面的條款34。

c 繼承機制易犯的錯誤

繼承作為物件導向的基本特徵之一,其使用率極高。不管是為了實現軟體的基本功能,還是再程式的重構的過程中,我們總是會用到繼承機制。正是因為其用途極為廣泛,而且使用簡單,大眾程式設計師對其真正的內部實現機制的 不是很深。而且,在大部分情況下,我們對繼承的使用方法是錯誤的。下面用例子來說明問題。cpp vi...

c 中易犯的錯誤

變數定義 用於為變數分配儲存空間,還可為變數指定初始值。程式中,變數有且僅有乙個定義。變數宣告 用於向程式表明變數的型別和名字。定義也是宣告 當定義變數時我們宣告了它的型別和名字。extern關鍵字 通過使用extern關鍵字宣告變數名而不定義它。1.定義也是宣告,extern宣告不是定義,即不分配...

C語言指標學習中易犯的錯誤

1 向null位址處copy資料 char str null strcpy str,aaaaabbbbb 錯誤!null是作業系統保護的空間,不能往裡面拷貝資料 2 void swap int a,int b 錯誤案例 不能實現實參a,b的互換 void swap int a,int b 在函式呼叫...