我有對象「的標識符」的列表導出(長枚舉列表,每個「識別符」的唯一值):C++保持指針到模板對象的集合,所有來自非模板
enum Identifier {
Enum0, // an identifier for a bool value
Enum1, // ... for a float value
Enum2, // ... for an int value
// etc.
};
我希望維護與這些標識符關聯的Value對象的集合。 hese Value對象包含單個值,但此值可能是整數,浮點數,布爾值或其他(簡單)類型。這是在管理系統中的一組配置值的情況下。稍後,我計劃擴展這些值類型以支持內部值的驗證,並將一些值與其他值相關聯。
但是我希望爲這些Value類使用模板,因爲我想一般地在這些值上編寫操作。如果我要使用繼承,我會有BaseValue,然後從BaseValue派生IntValue,FloatValue等。相反,我有價值,價值等
但我也想存儲一個訪問機制,每個這些值在一個集合。我想讓一個類實例化它們並將它們保存在集合中。如果我使用繼承,我可以使用指向BaseValue的向量。但是因爲我使用的是模板,所以這些類彼此之間沒有多態關係。
所以我想到了讓他們基於一個(空?)抽象基類,它是不參數化:
class BaseParameter {
};
template<typename T>
class Parameter : public BaseParameter {
public:
explicit Parameter(T val) : val_(val) {}
void set(ParameterSource src) { val_ = extract<T>(src); }
T get() { return val_; };
private:
T val_;
};
注意「設置」成員函數需要一個「ParameterSource」,這是由特定的「to_type」函數「重新解釋」的值的來源。這是一個不受我控制的API函數 - 我必須自己解釋這個類型,因爲我知道類型的意思,下面設置。這就是提取所做的 - 它專用於各種T類型,如float,int,bool。
然後,我可以將它們添加到一個std ::矢量這樣的:
std::vector<BaseParameter *> vec(10);
vec[Enum0] = new Parameter<bool>(true); // this is where I state that it's a 'bool'
vec[Enum1] = new Parameter<float>(0.5); // ... or a float ...
vec[Enum2] = new Parameter<int>(42); // ... or an int ...
我知道,我也許應該使用的unique_ptr但現在我只是試圖讓這個工作。到目前爲止,這似乎工作正常。但是我很謹慎,因爲我不確定實例化模板的完整類型是否會在運行時保留。
通過任意的枚舉值後來我要編制索引的「VEC」,檢索參數並調用關於它的成員函數:其利用這些配置值的
void set_via_source(Identifier id, ParameterSource source) {
// if id is in range...
vec[id]->set(source);
}
和其他代碼(因此知道類型)可以訪問他們:
int foo = vec[Enum2]->get() * 7;
這似乎工作,大部分時間。它編譯。我遇到了一些我無法解釋的奇怪的崩潰,這也導致調試器崩潰。但我對此非常懷疑,因爲我不知道C++是否能夠確定指向對象的實際類型(包括參數化類型),因爲基類本身沒有參數化。
不幸的是,在我看來,如果我參數化基類,那麼我基本上刪除了這些Value類之間的通用性,這些類允許它們存儲在一個容器中。
我看了一下boost :: any,看看是否有幫助,但我不確定它適用於這種情況。
在更高層次上,我試圖做的是連接來自外部源(通過API)的大量配置項目集合,該配置項目根據項目提供不同類型的值,並將其存儲在本地,以便我的其他代碼可以很容易地訪問它們,就好像它們是簡單的數據成員一樣。我也想避免寫一個巨大的開關語句(因爲這會起作用)。
Type Erasure可以幫助我嗎?
我甚至不明白爲什麼'int foo = vec [Enum2] - > get()* 7;'永遠不會編譯。你正在使用一個沒有定義方法的'BaseClass'指針 - 因此你無法(合法地)調用任何你從'vector'中取出的東西。你甚至不能在這裏使用'dynamic_cast',因爲它沒有定義'virtual'方法。 – Yuushi
你的懷疑是沒有根據的。這個設計是一個非常普遍的設計,它的工作原理(假設你有基本的虛擬獲取和設置方法)。如果你有崩潰,詢問你的具體崩潰。 –
@ n.m。看看上面提供的'BaseParameter'的定義,並告訴我你在哪裏可以看到一個'virtual'函數聲明。 – Yuushi