2017-07-30 63 views
1

C++中的初學者很容忍我。何時在overriden函數中調用上層的函數?在其他代碼之前或之後?

當你有一個虛擬重寫函數時,你應該什麼時候調用基本函數?它應該是這樣的:

void Player::onCollision (Collidable& otherObject) 
{ 
    /* OTHER CODE */ 
    /* OTHER CODE */ 

    PhysicalActor::onCollision (otherObject); 
} 

或者這樣:

void Player::onCollision (Collidable& otherObject) 
{ 
    PhysicalActor::onCollision (otherObject); 

    /* OTHER CODE */ 
    /* OTHER CODE */ 
} 

現在我不知道居然有這個設置的規則 - 它是否應該總是先走或總是走到最後,甚至在中間。我嘗試了谷歌搜索,但我不知道該怎麼樣谷歌,因爲標題花了我5分鐘寫出來,而且我不認爲我在任何已讀的書籍中都記得這一點。我總是選擇第二個,因爲在我的腦海中,你應該先處理更通用的東西,然後再處理更具體的東西。

對不起,如果這是一個簡單的問題!

謝謝!

+2

沒有設定規則。無論您的設計是否合理。 –

+1

取決於你想做什麼......這一切都取決於你。 – Papipone

+0

謝謝你們,我在想這個。你是否應該瞄準某些特定的東西?一種方法通常被認爲是更好的編碼標準嗎? – Dan

回答

1

語言中沒有這樣的要求。這是一個界面設計問題,儘管庫有時需要在特定時間調用基類,但我認爲這是一個糟糕的API。

最好的設計沒有要求用戶調用基本版本...永遠。這消除了派生類作者的任何負擔。我聽說過這種叫做的無合同 api設計,因爲沒有必須接受爲了覆蓋功能而達成的協議。

通常,您可以讓用戶接受這些合同,它將基類邏輯與客戶端覆蓋的部分混合在一起。所以不是:

class Base { 
//... 
public: 

    // ** this version must be called before an override does anything 
    virtual void doSomething() { 
     prepare(data); 
    } 

private: 
    Data data; 
} 

這就要求如果你重寫doSomething,你必須在做任何事之前先調用基本版本。

一個更好的界面會是這樣的:

class Base { 
//... 
public: 
    void doSomething() { // ** NOT virtual 
     prepare(data); 
     doSomethingHook(); 
    } 
protected: 
    virtual void doSomethingHook() { } // default is to do nothing 

private: 
    Data data; 
} 

這保證了任何調用DoSomething的()總是會得到重寫的虛函數之前準備的數據被調用,而現在的虛擬邏輯移動「在側面稍微「放入一個沒有排序責任的掛鉤函數,只有責任做它應該做的任何事情。

當然,doSomethingHook 可能是純虛擬的,但是一些掛鉤是完全沒有要留下一個空的實現,因爲他們的目的是要提供派生類選項在某些點行爲進行自定義。

+0

非常感謝這個答案和解決方法,我從來沒有想過。我很可能會在某個時候使用它。 +1 – Dan

相關問題