2011-12-19 71 views
6

我正在實現一個C++程序,該程序可以編程實例化給定輸入文件的對象,該輸入文件提供要傳遞給構造函數的類名稱和參數。具有異構構造函數約束的C++工廠模式

這些類是從一個公共基類派生的,但它們的構造函數簽名有所不同。

它們的聲明如下:

class Base { ... } 
class Class1 : Base { Class1(int a1, int a2); } 
class Class2 : Base { Class2(int a1, int a2, int a3); } 
... and so on... 

的參數類型沒有爲int的,事實上,他們可以是任何內置類型或複雜的自定義類型。

程序輸入可能看起來像這樣以JSON形式:

[ 
    { "Class1": ["arg11", "arg12"] }, 
    { "Class2": ["arg21", "arg22", "arg23"] }, 
    ...and so on... 
] 

閱讀過的文檔進行Boost.Functional/Factory看來,它可以解決我的問題,如果不是事實,我的應用程序構造函數簽名的變化(異質性約束)。 Boost.Function/Factory的方法是規範化構造函數簽名,但這在我的應用程序中是不可行的。

在像Python這樣的動態語言中,這將是相當平凡的:obj = klass(*args)其中klass = Class1args = ["arg11, "arg12"]

那麼如何實現工廠模式與C++中的異構約束呢?

除了Boost以外,還有其他的庫,我忽略了這可能是有幫助的嗎?

是否有可能實現這樣的唯一依賴項是標準庫(即不提升)?

此外,在構造函數參數是複雜類型的情況下,它必須從其JSON表示特別構造,它是如何影響問題的複雜性的?

+0

供將來參考,均勻的相對是異質 –

+2

嘿塞特, 「不均勻」也根據韋氏字典一個有效字,並且在意義「不同」的相似。 我選擇了前者,因爲這也是Boost.Function/Factory文檔的選擇(請參閱我的文章中的鏈接)。 –

+0

是的,我知道,你可以添加「in」或「un」幾乎任何單詞,它仍然是一個單詞。這聽起來很奇怪。 –

回答

1

要達到你想要什麼,你需要在代碼中的某個點上,一個巨大的switch語句來決定構建基於名稱(實際上,一個switch哪一類將無法工作,因爲您無法打開字符串 - 更像是很長的if - else if)。

此外,您顯示的表示看起來似乎不包含有關構造函數參數類型的任何信息。如果你有一個具有多個構造函數的類可以調用相同數量的參數,那麼這可能是一個問題。

最後,我認爲最好的做法是用@selbies answer之類的東西,但使用代碼生成爲您生成構建代碼。

+0

謝謝@bjorn&selbie。 對於我的用例,最好的答案是代碼生成。 我的代碼生成器是〜100行Python,並生成_approximately_有效的工廠函數。即我必須按摩一些生成的代碼。即使使用不完美的代碼生成器,我在完成此任務方面也非常有成效。 它可能仍然值得擴展Boost.Functional /工廠爲我的用例。稍後再探討。 :) 僅供參考:C++頭文件解析庫:[CppHeaderParser庫](https://bitbucket.org/senex/cppheaderparser/src),這對我的需求是足夠的。 –

5

您是否考慮過爲每個知道如何從文件中讀取參數的「數組」中構造對象的類的工廠方法。

即:

// declared "static" in header file 
Class1* Class1::FactoryCreate(int argc, const char** argv) 
{ 
    if (argc != 2) 
     return NULL; // error 

    int a1 = atoi(argv[0]); 
    int a2 = atoi(argv[1]); 
    return new Class1(a1, a2, a3); 
} 

// declared "static" in header file 
Class2* Class2::FactoryCreate(int argc, const char** argv) 
{ 
    if (argc != 3) 
     return NULL; // error 
    int a1 = atoi(argv[0]); 
    int a2 = atoi(argv[1]); 
    int a3 = atoi(argv[2]); 
    return new Class2(a1, a2, a3); 
} 
+0

我當然已經考慮過一個類似於此的選項......即將JSON對象傳遞給靜態工廠函數並讓它返回實例。問題是我正在處理的代碼庫有100多個這樣的類,並且這個類正在增長。所以雖然這肯定是一個可能的解決方案,但我現在毫不猶豫地稱它爲理想。 –