2014-12-03 79 views
3

在我目前的項目中,我需要能夠提供基於模板的多重繼承(Mixin模式)有兩個類(使用鏡像多重繼承樹)可以一起交互(即一個使用來自另一個方法的相同繼承級別的方法)。長長的故事,我似乎無法找到一個優雅的方式來建立這個。下面是一個簡化的測試用例(您可以直接運行並編輯它here)。基於模板的多重繼承爲兩個交互類...

有沒有一種模式或竅門,讓我有類似的評論行,同時保持任何子類相對cruft-free?

顯然,嵌套的Thing類需要從另一個類繼承,提供必要的接口方法。然而,在固定的繼承問題的任何嘗試(CRTP ...)似乎總是使我遞歸繼承或不完整的基本類型的問題...

class Base { 
public: 

    class Thing { 
    public: 
     Thing(Base& b) : _b(b) {}; 

     Thing& operator+= (const Thing p) { _b.add(*this, p); return *this; }; 

     int k; 
    protected: 
     Base& _b; 
    }; 

    void add(Thing &d, const Thing s) { d.k += s.k; } 
}; 

template <class... Interfaces> 
class Extensible : virtual public Base, virtual public Interfaces... { 

    class Thing : virtual public Base::Thing, virtual public Interfaces::Thing... { 

    }; 
}; 

class SomeInterface : Base { 
    void multiply(Thing &d, const Thing s) { d.k *= s.k; } 

    class Thing : public Base::Thing { 
     Thing& operator*= (const Thing p) { 
      //_b.multiply(*this, p); return *this; // <-- won't work of course 
     }; 

    }; 

}; 

int main() { 
    Extensible<SomeInterface> a; 
    return 0; 
} 

回答

1

這是其中的一個選項:http://ideone.com/KhLyfj(我只是告訴基類是什麼是它的子類給_b一個正確的類型)。但它在某些情況下不起作用。您可以嘗試將模板從Thing/add直接移動到Base

class Base { 
public: 

    template<typename Outer> 
    class Thing { 
    public: 
     Thing(Base& b) : _b(b) {}; 

     Thing& operator+= (const Thing p) { _b.add(*this, p); return *this; }; 

     int k; 
    protected: 
     Outer& _b; 
    }; 

    template<typename Outer> 
    void add(Thing<Outer> &d, const Thing<Outer> s) { d.k += s.k; } 
}; 

template <class... Interfaces> 
class Extensible : virtual public Base, virtual public Interfaces... { 

    class Thing : virtual public Base::Thing<Base>, virtual public Interfaces::template Thing<Base>... { 

    }; 
}; 

class SomeInterface : Base { 
    void multiply(Thing<SomeInterface> &d, const Thing<SomeInterface> s) { d.k *= s.k; } 

    class Thing : public Base::Thing<SomeInterface> { 
     Thing& operator*= (const Thing p) { 
      _b.multiply(*this, p); return *this; // <-- will work of course 
     }; 

    }; 

}; 

int main() { 
    Extensible<SomeInterface> a; 
    return 0; 
} 
+0

感謝您的建議:它聽起來像一個有前途的方向(不得不做一些補充,讓我實例化「物體」)。除了這會導致無法在主類中使用'_b'的鑽石問題:http://ideone.com/YrrpBn – Dave 2014-12-04 08:05:25

+0

請嘗試此操作,然後:http://ideone.com/TOKP8b。我已經添加了'SomeInterface'的前向聲明,'Base'是'Extensible'的虛擬基類,'SomeInterface :: Thing'具有顯式構造函數,'Extensible :: Thing'的構造函數顯式調用'Base ::事 ::東西(E)'。這是一個非常好的謎題:)。 – matb 2014-12-04 10:41:00

+0

非常感謝您的努力......不幸的是,前向聲明(以及在Extensible中的使用)有點挫敗了接口模式的目的(要求我們先發制人地繼承我們所有的接口)。我設法得到了一些代碼:http://ideone.com/sblnfM 無論如何,我正在接受你的答案。隨意將其與此代碼合併。 – Dave 2014-12-04 18:08:42