2015-04-04 79 views
0

我經常遇到與SubType Polymorphism相關的問題,我正在尋找一個我可能不知道的優雅解決方案。調用基於運行時邏輯的模板化C++方法

下面是一個簡單的繼承層次:

struct BaseClass { 
    virtual ~BaseClass() = 0; 
    std::string name; 
}; 

template <T> 
struct DerivedClass 
{ 
    DerivedClass(const std::string& _name): name(_name) { } 
}; 

現在,我可能會產生很多不同的名字和模板類型,這些DerivedClass實例並使用他們的BaseClass它們存儲在陣列中。

std::vector<BaseClass*> array; 
array.push_back(new DerivedClass<TABC>("abc")); 
array.push_back(new DerivedClass<TDEF>("def")); 
... 

這是非常標準的運行時多態性。

然而,當我有功能的新層的類型是專用的添加和不希望這個新層在兩個方向耦合,我最終不得不做這樣的事情:

template <typename T> 
void method(DerivedClass<T>* object) { } 

void callMethod(BaseClass* object) 
{ 
    // this is the logic I'm trying to move up a layer 

    if (object->name == "abc")  method<TABC>(object); 
    else if (object->name == "def") method<TDEF>(object); 
} 

這些方法中的每一個都必須具有相同的運行時字符串列表才能進行編譯時類型轉換,這意味着添加新類型需要進行大量更改。

如果我假定新圖層只支持編譯時已知的特定選項(就像這裏的情況一樣),那麼在運行時添加新類型是可行的,但不能使用它們在這一層,這將是很好的。我現在的想法是,如果我將虛擬方法引入帶有函數指針的類層次結構中,我可以根據特定的編譯時類型爲第二層中的每個方法註冊函數指針(理想情況下只指定一次),有點像雙調度類型的方法。

有什麼想法,建議嗎?

+0

爲什麼你不能將模板移動到基地? – 2015-04-04 14:48:02

+0

我確實需要能夠一般性地存儲這些數據,因此我可以在其他用例中使用多態性。 – Dan 2015-04-04 15:21:34

回答

3

你需要一個鏈接調用基於字符串的特定模板版本,你能做的最好是有string詞典 - >lambda function和使用字符串作爲查找得到function<>打電話。這避免了嵌套的if,並且在編譯時(缺省列表)和運行時(任何更改只是數組更改)都相對容易維護。

+0

謝謝,這符合我的想法。問題是如何建立這些列表。如果我有多個這樣的字符串 - >函數列表,我只想真的想指定我曾經使用的函數和類型一次,然後執行所有的映射來構建所有的排列組合? (也不能在這個應用程序中使用C++ 11)。 – Dan 2015-04-04 15:20:09

+0

使用宏來構建函數對象,並在函數名稱中插入模板參數以確保唯一性。 Lambda函數只不過是沒有名字的正常函數(即編譯器生成的名稱)。然而,你應該重新考慮你的任意限制,C++ 11是4歲。如果你現在不能使用它,你什麼時候可以? – Blindy 2015-04-04 21:48:52