所謂介面繼承,就是派生類只繼承函式的介面,也就是宣告;而實現繼承,就是派生類同時繼承函式的介面和實現。
我們都很清楚c++中有幾個基本的概念,虛函式、純虛函式、非虛函式。
虛函式:
虛函式是指乙個類中你希望過載的成員函式,當你用乙個基類指標或引用指向乙個繼承類物件的時候,你呼叫乙個虛函式,實際呼叫的是繼承類的版本。——msdn
虛函式用來表現基類和派生類的成員函式之間的一種關係.
+`%k i;l"z @2j-^5/0虛函式的定義在基類中進行,在需要定義為虛函式的成員函式的宣告前冠以關鍵字 virtual. 航大部落格-中國民航大學個人門戶n-d&;
class rectangle: public shape ;
class ellipse: public shape ;
shape 是乙個 abstract class(抽象類),它的 pure virtual function(純虛函式)表明了這一點。作為結果,客戶不能建立 shape class 的例項,只能建立從它繼承的 classes 的例項。但是,shape 對所有從它(公有)繼承的類施加了非常強大的影響,因為
成員函式 inte***ces are always inherited。就像 item 32 解釋的,public inheritance 意味著 is-a,所以對乙個 base class 來說成立的任何東西,對於它的 derived classes 也必須成立。因此,如果乙個函式適用於乙個 class,它也一定適用於它的 derived classes。
shape class 中宣告了三個函式。第乙個,draw,在乙個明確的顯示裝置上畫出當前物件。第二個,error,如果 member functions 需要報告乙個錯誤,就呼叫它。第三個,objectid,返回當前物件的唯一整型識別符號。每乙個函式都用不同的方式宣告:draw 是乙個 pure virtual function(純虛函式);error 是乙個 ****** (impure?) virtual function(簡單虛函式);而 objectid 是乙個 non-virtual function(非虛函式)。這些不同的宣告暗示了什麼呢?
考慮第乙個 pure virtual function(純虛函式)draw:
class shape ;
pure virtual functions(純虛函式)的兩個最顯著的特性是它們必須被任何繼承它們的具體類重新宣告,和抽象類中一般沒有它們的定義。把這兩個特性加在一起,你應該認識到。
宣告乙個 pure virtual function(純虛函式)的目的是使 derived classes 繼承乙個函式 inte***ce only。
這就使 shape::draw function 具有了完整的意義,因為它要求所有的 shape 物件必須能夠畫出來是合情合理的,但是 shape class 本身不能為這個函式提供乙個合乎情理的預設的實現。例如,畫乙個橢圓的演算法和畫乙個矩形的演算法是非常不同的,shape::draw 的宣告告訴具體 derived classes 的設計者:「你必須提供乙個 draw function,但是我對於你如何實現它不發表意見。」
順便提一句,為乙個 pure virtual function(純虛函式)提供乙個定義是有可能的。也就是說,你可以為 shape::draw 提供乙個實現,而 c++ 也不會抱怨什麼,但是呼叫它的唯一方法是用 class name 限定修飾這個呼叫:
shape *ps = new shape; // error! shape is abstract
shape *ps1 = new rectangle; // fine
ps1->draw(); // calls rectangle::draw
shape *ps2 = new ellipse; // fine
ps2->draw(); // calls ellipse::draw
ps1->shape::draw(); // calls shape::draw
ps2->shape::draw(); // calls shape::draw
除了幫助你在雞尾酒會上給同行程式設計師留下印象外,這個特性通常沒什麼用處,然而,就像下面你將看到的,它能用來作為乙個「為 ****** (impure) virtual functions 提供乙個 safer-than-usual 的實現」的機制。
****** virtual functions 背後的故事和 pure virtuals 有一點不同。derived classes 照常還是繼承函式的 inte***ce,但是 ****** virtual functions 提供了乙個可以被 derived classes 替換的實現。如果你為此考慮一陣兒,你就會認識到
宣告乙個 ****** virtual function 的目的是讓 derived classes 繼承乙個函式 inte***ce as well as a default implementation。
考慮 shape::error 的情況:
class shape ;
inte***ce 要求每乙個 class 必須支援乙個在遭遇到錯誤時被呼叫的函式,但是每乙個 class 可以自由地用它覺得合適的任何方法處理錯誤。如果乙個 class 不需要做什麼特別的事情,它可以僅僅求助於 shape class 中提供的錯誤處理的預設版本。也就是說,shape::error 的宣告告訴 derived classes 的設計者:「你應該支援乙個 error function,但如果你不想自己寫,你可以求助 shape class 中的預設版本。」
結果是:允許 ****** virtual functions 既指定乙個函式介面又指定乙個預設實現是危險的。來看一下為什麼,考慮乙個 xyz 航空公司的飛機的 hierarchy(繼承體系)。xyz 只有兩種飛機,model a 和 model b,它們都嚴格地按照同樣的方法飛行。於是,xyz 設計如下 hierarchy(繼承體系):
class airport ; // represents airports
class airplane ;
void airplane::fly(const airport& destination)
class modela: public airplane ;
class modelb: public airplane ;
為了表述所有的飛機必須支援乙個 fly 函式,並為了「不同機型可能(在理論上)需要不同的對 fly 的實現」的事實,airplane::fly 被宣告為 virtual。然而,為了避免在 modela 和 modelb classes 中些重複的**,預設的飛行行為由 airplane::fly 的函式體提供,供 modela 和 modelb 繼承。
這是乙個經典的 object-oriented 設計。因為兩個 classes 共享乙個通用特性(它們實現 fly 的方法),所以這個通用特性就被轉移到乙個 base class 之中,並由兩個 classes 來繼承這個特性。這個設計使得通用特性變得清楚明白,避免了**重複,提公升了未來的可擴充套件性,簡化了長期的維護——因為 object-oriented 技術,所有這些東西都受到很高的追捧。xyz 航空公司應該引以為榮。
C 介面繼承與實現繼承
介面繼承與實現繼承 moakap 所謂介面繼承,就是派生類只繼承函式的介面,也就是宣告 而實現繼承,就是派生類同時繼承函式的介面和實現。我們都很清楚c 中有幾個基本的概念,虛函式 純虛函式 非虛函式。虛函式 虛函式是指乙個類中你希望過載的成員函式,當你用乙個基類指標或引用指向乙個繼承類物件的時候,你...
C 介面繼承與實現繼承
介面繼承 派生類只繼承函式的介面 實現繼承 派生類同時繼承函式的介面和實現 虛函式是過載的一種表現方式,是一種動態的過載方式。非虛函式 繼承該函式的介面和乙份強制性實現。虛函式 會繼承該函式的介面和預設實現。純虛函式 純虛函式在基類中沒有定義,介面繼承。含有純虛函式的類無法例項化。總結來說 純虛函式...
C 之實現繼承與介面繼承
之前讀設計模式的時候突然看到這樣的兩個詞語,心裡咯噔了一下,沒有能夠一下反應出這個是什麼意思,於是去google了一下。瞬間覺得自己弱爆了,連這個都不知道。在c 中,有純虛函式和簡單虛函式這一說。純虛函式一般定義沒有直接的定義,定義需要在子類中具體給出。而對於簡單虛函式來說,如果你不想去重新定義的時...