2010-01-15 96 views
3

我正在尋找一種方法來確定在運行時應分配哪種類型的對象(基於給定的類名稱,其類型爲const char*)。如何獲得給定類名稱的未知類的對象

嘛,當然最簡單的方法是使用if S/else if小號加載,但似乎不適用,因爲我有> 100個不同的類別(以及至少他們都來自同一個基類派生),我有定期增加新課程。

我已經想出了一個初稿,但遺憾的是它不編譯,但(MinGW的& G ++ 4.4)

template<typename TBase, typename TDerived, typename... TArgs> 
Base* get_classobject(const char* classname) 
{ 
    if(strcmp(classname,typeid(TDerived).name())==0) 
     return new TDerived; // 
    else if(sizeof...(TArgs)>0) 
     return get_classobject<TBase,TArgs...>(classname); 
    else 
     return 0; 
} 


int main() 
{ 
    Base* obj = get_classobject<Base,A,Foo,B,C>("Foo"); 
    // ^- Types A B C and Foo are all derived from Base 
    delete obj; //of course we got an virtual dtor ;) 
    return 0; 
} 

但試圖生成代碼sizeof...(TArgs)>0犯規停止GCC爲get_classobject<TBase,const char*>(const char*)從而未能

你有任何想法,如何解決這個問題,或任何其他想法? 謝謝。

編輯:我解決了這個問題:

template<typename TBase, typename TDerived> 
Base* get_classobject(const char* classname) 
{ 
    if(strcmp(classname,typeid(TDerived).name())==0) 
     return new TDerived; 
    return 0; 
} 

template<typename TBase, typename TDerived, typename TArg, typename... TArgs> 
Base* get_classobject(const char* classname) 
{ 
    if(strcmp(classname,typeid(TDerived).name())==0) 
     return new TDerived; 
    return get_classobject<TBase,TArg,TArgs...>(classname); 
} 

編輯感興趣的讀者:
您現在應該是執行上面沒有編譯器無關的。 typeif(sometype).name()的輸出是編譯器/實現特定的。 在所有派生類中使用static const char* name變量或函數,可以解決這個問題,但會添加一些工作(當然,您可以使用宏來實現此目的,但是如果您已經使用宏,則可以使用另一個對象工廠方法)

+0

聞起來就像你需要實現一個工廠和'clone'方法。使用'clone()'接口,你可以創建一個家族的對象,而不需要知道他們的類名。 – 2010-01-16 01:04:17

+0

我不想看起來很重要,但真的......這味道不好。首先,'typeid'的使用是頗有爭議的,但我也想指出這種方法的低效性>你執行一個線性複雜的搜索,並且你必須精確地確定所有可能生成的類型。 ..我甚至不想考慮噩夢般的維護成本。 – 2010-01-16 16:47:30

+0

typeid可以很容易地用static :: name函數代替,線性搜索不是一個問題,因爲我只調用這個方法一次(除此之外,任何其他對象工廠ive看過也有一個線性搜索或濫用宏) – smerlin 2010-01-16 19:03:47

回答

3

你就不能申報

template<typename TBase, typename TDerived, typename TArg, typename... TArgs> 

然後你就可以專門爲

typename TBase, typename TDerived, typename TArg 
+0

wouldnt它甚至如果我這麼做了,那麼先遞交一個遞歸步驟? – smerlin 2010-01-15 22:36:26

+0

你正試圖獲得1 +模板參數,而不是0+對嗎?您可以專門針對0個案例的模板。一旦我瞭解你, – 2010-01-15 22:40:02

+0

就像一個魅力。 – smerlin 2010-01-15 23:30:32

2

的情況下閱讀的答案在here,你可能需要一個工廠。

0

這聽起來像你正在尋找經典的對象工廠模式。看看這個stackoverflow question。我個人喜歡這個method

+0

使用該模式時,您必須自己編寫代碼,使用我的方式編譯器爲我生成;) – smerlin 2010-01-15 23:33:03

+0

@smerlin如果我理解*您的*方式,您需要在每次需要調用時鏈/寫所有派生類'get_classobject()'。所以當添加一個類或刪除一個時,這是一個管理/手動過程。我描述的方式是多一點*自動*。基本上你只需要添加兩行。類聲明中的METADECL和編譯單元(.cpp文件)中的METAIMPL,最好靠近構造函數。這個解決方案的自動化功能是真正吸引我的,然後通過加載共享對象(.so/.dll文件)甚至可以在運行時添加類。完成了... – epatel 2010-01-16 00:25:50

+0

無論如何我只需要調用這個函數,並且如果我不得不多次調用它們,我會添加一個(內聯)包裝函數,這樣我只需要編寫一次類 – smerlin 2010-01-16 07:58:57

1

如何製作一個沒有可變參數的專門化get_classobject()?這將停止遞歸。

然後,您將有一個可變參數模板的定義,另一個只是template<typename TBase, typename TDerived>。另一個想法是做一個非模板重載,只接受const char *,並返回0.

+0

已經嘗試過了,仍然有 錯誤:沒有匹配函數調用get_classobject( const char *&)'|' – smerlin 2010-01-15 23:07:59