2012-12-03 36 views
2

我有以下問題(簡化版本):如何將typename傳遞給我不想模板化的類?

Interface X; 
class Y : public X { ... } 
class Z : public X { ... } 

class A 
{ 
    map<int, X> m; 
    init() { X bla = new Y or Z; map.insert(...) } 
} 

我想在A的創建時間來指定Y或Z,從而基於指定類型得到一個不同的功能。目前我可以「模板化」A,但這意味着我爲A定義的每個函數都必須指定模板,即使我只需要在一種方法中使用它。此外,我使用g ++ 4.2.4,這意味着我不能將我的函數實現從頭文件中分離出來。

回答

2

...即使我只需要在一個方法來使用它...

什麼通常在這種情況下,做的是移動通用的功能,這是不模板化,到基地類,並定義了繼承基本功能的模板化A。 I.e .:

class A_base { 
    // common things go here, they can be implemented in a .cpp file. 
}; 

// This is the part that depends on T 
template<class T> 
class A : public A_base 
{ 
    map<int, T> m; 
    void init() { T *bla = new T; map.insert(...) } 
}; 

這是減少代碼膨脹的常用技術。如果A_base需要調用A的方法,則可以使其成爲virtual

+0

這似乎完全符合我的法案。謝謝。 – NindzAI

+0

值得注意的是'init'需要是'virtual'才能正常工作。 –

+0

@MatteoItalia:不,它不是。這取決於誰在調用'init()'。例如,如果'init'是構造函數,那麼它不僅不必是'虛擬',實際上它不可能是這樣的。 – ybungalobill

2

如果,因爲它從使用new看來,它實際上map<int, X*> mX* bla=...,你可以在「模板化」只是init(),創造了YZ從它的模板參數依賴。

或者,您可以有一個工廠方法,用於返回Y *Z *X衍生對象,具體取決於enum;或讓init的調用者指定一個工廠函數,該函數返回適當的X衍生類型。

+0

謝謝你的回答。這是我考慮的事情,但init是從A類內調用的 - 現在必須存儲額外的數據以知道實例化的類型。我試圖避免在課堂上增加額外的變量 - 它已經太多了。 =) – NindzAI

3

聽起來像模板確實是矯枉過正,某種形式的依賴注入更合適。你可以在傳遞的X特定實例A::init,例如:

init(X &bla) { map.insert(...); } 

或者通過在工廠函數:

init(X (*factory)()) { X bla = factory(); map.insert(...); } 

?或者兩者但通過實例或工廠功能的構造函數A

+0

謝謝你的回答。這是一個很好的方法 - 我需要記住它。 – NindzAI

相關問題