2012-01-09 15 views
5

我有一個基類和派生自它的類。基類Controllable充當輸入循環的接口,其他類從它派生出來以便在該循環中獲得一個位置,以獲得事件,如按下按鍵時。C++:需要調用相同代碼的虛函數?

class Controllable{ 
public: 
    virtual void setActive(bool state) { m_active = state; } 
    virtual void input(Event & e) =0; 
private: 
    bool m_active; 
}; 

class Button : public Controllable{ 
public: 
    void setActive(bool state){ /*do extra work*/ m_active = state; } 
    void input(Event & e) override; 
}; 

因爲從事件隊列事件Button類處理,將其設置爲不活動(這需要它的輸入迴路的)可能會導致其錯過像一個關鍵重要的事件是未壓榨,所以需要額外的代碼將其置於友好的非活動狀態,以便稍後再次激活它。

我的問題,什麼是保證setActive總是有切換m_active到正確狀態的預期效果最好的方式,而在同一時間,不要求派生類,除非他們需要附加額外的定義它需要的代碼?

+0

你','的功能後'}',看着他們。 – 2012-01-09 18:15:03

+0

Mr.TAMER - 修好了!我有一個很癢的;手指 – 2012-01-09 18:20:54

回答

9

保持setActive方法非虛,然後定義一個單獨protected方法activeChanged,該子類可以覆蓋

class Controllable{ 
public: 
    void setActive(bool state) { m_active = state; activeChanged(state); } 
    virtual void input(Event & e) = 0; 
protected: 
    virtual void activeChanged(bool newState) {} 
private: 
    bool m_active; 
} 

class Button : public Controllable{ 
protected: 
    void activeChanged(bool newState){ /*do extra work*/ } 
public: 
    void input(Event & e); 
}; 

通過這種方法,你都讓外界公共接口從保護內部分離旨在用於子類的接口。

+0

謝謝!我沒有想到以這種方式使用非虛擬方法。我有很多其他的基礎類可以從這種治療中受益。 – 2012-01-09 18:36:01

+0

'activeChanged'應該是私有的,不受保護,因爲派生類永遠不需要調用基類的實現,只能覆蓋它。 – ildjarn 2012-01-09 19:48:36

+0

輕微的「錯誤」:即使沒有改變狀態,你也會調用'activeChanged()',儘管它的名字沒有改變(就像'm_active'的計算結果爲true並且你再次調用'setActive(true)')。 – Mario 2012-01-10 09:17:56

1

如何使setActive()非虛擬,而是添加setActive()調用的第二個虛擬成員(例如onSetActive())?

6

的一種方法是定義「前」和「後」虛擬方法:

class Controllable{ 
public: 
    void setActive(bool state) { 
     preSetActive(m_active, state); 
     m_active = state; 
     postSetActive(m_active); 
    }; 
    virtual void input(Event & e) =0; 
protected: 
    virtual void preSetActive(bool oldState, bool newState) {} 
    virtual void postSetActive(bool newState) {} 
private: 
    bool m_active; 
} 

注意,setActive()方法是在這種技術不虛擬。

+0

哦,很酷。在這種情況下,前後有兩個函數可能會矯枉過正,但我​​還有其他一些類,這將是完美的。謝謝! – 2012-01-09 18:24:11

1

我的2美分: 拆2個的任務之間的行爲:

virtual doActive(){}; //doNothing 
void setActive (bool state) { 
    m_active = state; 
    doActive(); 
}