2013-03-23 39 views
6

我遇到了一個設計問題,其中(在C++中)我希望模板成員函數(非模板類)是虛擬的我想知道是否有一個好的,優雅的方式解決這個問題。如何設計模板化成員函數不能虛擬的限制

的情況下得好,我有過程通用項目。我使用抽象基類機器虛擬進程(Item)函數,使每臺機器都可以定義自己獨特的處理方法。問題是這些項目也是「通用的」,因爲它們公開了某些接口以便如何處理它們。由於某些原因(主要是爲了......沒有vtable開銷),我想爲這些項目使用編譯時多態性。所以,現在每個機器將具有等的接口:

class Machine 
{ public: 
    template <typename T> 
    virtual void process(T& item) = 0; 
}; 

然而,這是用C++不可能作爲模板構件功能不能是虛的。當然,我可以讓機器類在Item類型T上模板化,但這在更大的設計方案中爲我增加了更多麻煩,並且Machine類的其他部分實際上不依賴於Item ...它只是process()函數的一個參數。

有沒有更好的解決方法或任何有關如何提供處理一系列通用項目(其中項目使用編譯時多態)的通用系列機器的建議。在我的設計方面,我的表現有多深?

感謝任何建議

+0

那麼特定的機器可以處理任何類型的物品?和項目類型本質上是不相關的,還是你可以創建一個'Item'超類? – 2013-03-23 21:47:59

+1

您是否需要通過指向抽象'Machine'類的指針訪問具體機器?如果沒有(如果你可以通過具體類訪問它),[CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)是要走的路(關鍵詞:「靜態多態性」)。 – leemes 2013-03-23 21:48:05

+0

您有兩種選擇:CRTP和雙派遣。在這裏你說你不想要雙重調度,但這可能是不成熟的優化(想想它)。 – 2013-03-23 21:51:33

回答

3

通常情況下,使用雙派遣。

class Machine; 
class Item { 
public: 
    virtual void bounce(Machine& mach); 
}; 
class Machine { 
public: 
    template<typename T> void process(T& t); 
    virtual void process(Item& i) { 
     return i.bounce(*this); 
    } 
}; 
template<typename T> class CRTPItem { 
public: 
    virtual void bounce(Machine& mach) { 
     return mach.process(*(T*)this); 
    } 
}; 
class ConcreteItem : public CRTPItem<ConcreteItem> { 
public: 
    // blah blah 
}; 

在這種情況下,你不需要虛擬開銷整個ConcreteItem接口,並且它們並不需要什麼共同點,這是爲您自動從CRTPItem繼承建只是一個bounce功能。這只是兩個vtable調用,而不是原來的調用,而不是需要對所有Item的函數進行vtable調用,並且該界面仍然可以保留如果可以創建虛擬模板時所具有的所有強類型。

+0

是不是'CRTPItem <>'來源於'Item'? – 2013-03-23 22:07:11

+0

如果CTRPItem從Item派生,DerivedMachine的進程如何被調用? (即DerivedMachine會是什麼樣子)? – 2013-03-28 22:43:46

+0

@DeadMG如果CTRPItem從Item派生,DerivedMachine的進程如何被調用? (即DerivedMachine會是什麼樣子)? – 2013-03-29 14:46:36