2017-08-10 42 views
1

我有以下代碼使用多重繼承。目的是在派生類使用兩個接口,一個:哪個基類調用派生重寫方法?

struct InterfaceA 
{ 
    virtual void register_stuff(); 
    virtual void on_state_changed(const State state) = 0; 
}; 

struct InterfaceB 
{ 
    virtual void register_stuff(); 
    virtual void on_state_changed(const State state) = 0; 
}; 

struct Derived : InterfaceA, InterfaceB 
{ 
    void register_stuff() override 
    { 
     InterfaceA::register_stuff(); 
     InterfaceB::register_stuff(); 
    } 

    void on_state_changed(const State state) override 
    { 
     // how can I know who is responding? 
    } 
}; 

註冊的界面會造成on_state_changed的異步調用。是否有可能辨別哪個接口正在調用它?

+1

如果你需要這些信息,爲什麼不添加一個參數來告訴你你需要什麼? –

+1

或者乾脆不要使用多重繼承。 – Ron

+0

我覺得這個[文章](http://www.cprogramming.com/tutorial/multiple_inheritance.html)在陷阱小標題下有一些這方面的信息。 – Mekicha

回答

5

您必須在中間添加一層來消除歧義。這裏有一個小實用程序,可以即時創建它們:

template<class Inteface> 
struct disambiguate : Interface { 
    void on_state_changed(const State state) override final { 
    on_state_changed(state, this); 
    } 
    virtual void on_state_changed(const State &state, disambiguate*) = 0; 
}; 

就是這樣。然後,它在此實用程序來定義你的類的問題:

struct Derived : disambiguate<InterfaceA>, disambiguate<InterfaceB> 
{ 
    void register_stuff() override 
    { 
     InterfaceA::register_stuff(); 
     InterfaceB::register_stuff(); 
    } 

    void on_state_changed(const State &state, disambiguate<InterfaceA>*) override 
    { 
     // Called for A 
    } 

    void on_state_changed(const State &state, disambiguate<InterfaceB>*) override 
    { 
     // Called for B 
    } 
}; 

我用另一個參數和重載,使這個模板化,但該技術本身也可以通過寫班列和調用來完成具有新名稱的虛擬功能。關鍵是使原始虛擬調用(通過接口指針)達到調用消歧函數的短暫調用。

0

我正在考慮使用模板來消除歧義,但我相信@StoryTeller的答案更加優雅。

struct InterfaceA 
{ 
    virtual void register_stuff(); // calls on_state_changed<InterfaceA>() 

    template <typename Interface> 
    virtual void on_state_changed(const State state) = 0; 
}; 

struct InterfaceB 
{ 
    virtual void register_stuff(); // calls on_state_changed<InterfaceB>() 

    template <typename Interface> 
    virtual void on_state_changed(const State state) = 0; 
}; 

struct Derived : InterfaceA, InterfaceB 
{ 
    void register_stuff() override 
    { 
     InterfaceA::register_stuff(); 
     InterfaceB::register_stuff(); 
    } 

    template <typename Interface> 
    void on_state_changed(const State state) override 
    { 
     // how can I know who is responding? 
     // : "Interface" is responding 
    } 
}; 
2

或者,也可以直接在源性的代碼提供處理程序單獨實施:

struct Derived : InterfaceA, InterfaceB 
    { 
     void register_stuff() override 
     { 
      InterfaceA::register_stuff(); 
      InterfaceB::register_stuff(); 
     } 

     void InterfaceA::on_state_changed(const State state) override 
     { 
      // responding A 
     } 

     void InterfaceB::on_state_changed(const State state) override 
     { 
      // responding B   
     } 
    }; 

編輯:不幸的是這種解決方案是僅由Visual C++編譯器的非標準和支持。

+0

這不是爲我編譯的。你正在使用哪個編譯器+版本? – nyarlathotep108

+0

它是VS 2010.它應該是經典的C++。你遇到了什麼錯誤? – jszpilewski

+0

錯誤:無法在Derived中定義成員函數'InterfaceA :: on_state_changed' void InterfaceA :: on_state_changed(const State state)覆蓋{} ^ – nyarlathotep108

相關問題