2014-09-01 48 views
1

我(希望)已經理解了私人虛擬功能的目的,但我還沒有理解爲什麼我應該有一個私人的純粹的虛擬功能! 我的意思是,我必須在所有派生類中定義這個函數,但這樣所有對這個虛擬的調用將是對派生類中定義的調用的調用。私人純虛擬功能的目的是什麼?

假設我們有:

class Base{ 
public: 
    void foo(){ bar(); } 
private: 
    virtual void bar() =0 {/*something*/} 
}; 

派生類基地必須定義欄(或有它的純虛擬的,但忘了這一個時刻)。 因爲Base :: bar是私有的,所以它不能被派生類使用。 由於Base是抽象的,我不能創建Base對象,因此我只能在派生類上調用foo,但這意味着Base :: bar永遠不會被調用! 當然,我可以定義富:

void Base::foo(){ 
    bar(); 
    Base::bar(); 
} 

但是爲什麼?用bar的主體定義一個非虛擬的私有函數會更好(並用它替換Base :: bar),並使純虛擬的主體爲空?

如果是這樣,爲什麼我應該有酒吧私人(而不是保護)?我試圖找到一個在互聯網上的解決方案,我知道有像職位 - >C++: Private virtual functions vs. pure virtual functions,但他們幫助理解私人虛擬功能,而不是私人PURE虛擬功能。如果我錯了,請原諒我!

+0

'virtual void bar()= 0 {/ * something * /}'? – ChiefTwoPencils 2014-09-01 00:03:02

+1

您不必爲純虛函數提供定義,如果這就是您要求的。 – 2014-09-01 00:08:05

+0

@ T.C。我認爲你刪除了我正在迴應的評論。 – 2014-09-01 01:15:03

回答

1

所以在一般的模式是實現公共非虛函數和私有或受保護的虛擬函數,看起來您已經研究了這一點,但這通常被稱爲Template Method Pattern,Herb Sutter herehere的更多解釋。

是否使其成爲純虛擬取決於您的要求,有時絕對沒有默認行爲是有意義的,或者您希望強制所有子類實現它們自己的此虛擬功能版本。有時候一個空的實現是有意義的。然後提供,但是會發生什麼情況是其他實現者可能會忘記定製他們的類,而不是實現您爲其提供默認行爲的虛擬類。這實際上是一個個案決定,你將不得不作出。

在某些情況下,您希望爲純虛函數提供實現,Herb Sutter again,列出兩個,一個用於提供默認行爲,但強制派生類進行有意識地調用,另一個用於防止編譯器可能會得到一個純虛函數的問題。

在你的問題所在的地方會有各種各樣的擔憂,一般使虛擬函數爲私有的或受保護的,由公共函數(又稱爲模板方法模式)調用。如果派生類不需要調用超類實現,則將其設爲私有。如果要實現默認行爲,請將其保護起來並在更高級別中實施默認行爲。如果你想強制子類實現它們自己的功能(獨立於它們是否存在默認行爲),使它成爲純虛擬的。

+0

「有些角落案例需要爲純虛函數提供實現,Herb Sutter再次列出了兩個,一個提供默認行爲,但強制派生類有意識地調用」,這個原因可能是有效的,如果我有這個純粹的虛擬功能保護(或公共),但不是私人的。但是,第二個,可能是合理的:以防萬一,如果有一些錯誤發生,我會知道,並使其私人,我不讓派生類使用這種「警告」功能; .. – Toccio 2014-09-01 11:53:09

+0

..此外,使它純粹我強加的派生實現自己的(所以「警告」純虛擬不會被繼承)。最後,我做了一個「沒有主體的純虛函數」,因爲它通常不能調用(因爲我沒有定義它),所以避免了鏈接錯誤。 對嗎? (原諒我這個長時間的回覆!) – Toccio 2014-09-01 11:54:06

+0

是的,我認爲你說得對,我從來沒有添加過一個純虛擬函數的實體,並且在大多數情況下,我使用帶保護虛擬的模板方法。 – 2014-09-01 12:26:18

0

當然,bar()仍然可以由Base類的其他成員調用。

通過使bar()是純粹的,這具有迫使可實例化的子類實現bar()或從另一個可實例化類繼承的通常效果。

也許你明確不希望子類直接調用父類的酒吧(),並迫使子類來通過一些其他的保護方法,或兩個間接調用它...