2013-03-01 21 views
0

說我有名爲ItemOne,ItemTwo,ItemThree和ItemFour,它們都是ItemBase的所有子類的類的列表。C++ - 使用類名稱作爲函數參數

我想在另一個名爲ItemGenerator的類中有一個構造函數,它接受任何這些類的名稱。我將如何做到這一點?

ItemGenerator *someItem = new ItemGenerator(ItemThree); 

另一種選擇是在這些類中的一個上傳遞一個靜態函數,但是我不知道該怎麼做。

ItemGenerator *someItem = new ItemGenerator(ItemOne::start()); 

謝謝。

+0

看看「工廠」的設計模式。 – Max 2013-03-01 16:28:39

+1

你究竟想達到什麼目的?換句話說,'ItemGenerator'是用來處理類名還是'static'成員函數? – 2013-03-01 16:30:23

+0

這真的取決於你想如何使用構造函數中的類。你會得到大量不同的答案,它們會做出不同的假設,並得到不同的結果。 – 2013-03-01 16:40:14

回答

0

函數不能接受類的名稱作爲參數,因爲類不是C++中的對象。 但模板函數可以通過類名進行參數化。

事情是這樣的:

template<class T> 
ItemGenerator* ItemGeneratorFactory() { T::start(); ...} 

ItemGenerator *someItem = ItemGeneratorFactory<ItemThree>(); 
1

你可以使用一個模板:

struct ItemBase {virtual ~ItemBase();}; 
struct ItemOne : ItemBase {}; 
struct ItemTwo : ItemBase {}; 
struct ItemThree : ItemBase {}; 
struct ItemFour : ItemBase {}; 

struct ItemGeneratorBase { 
    virtual unique_ptr<ItemBase> generate() {} 
    virtual ~ItemGeneratorBase() {} 
}; 
template<typename Item> 
struct ItemGenerator : ItemGeneratorBase { 
    virtual unique_ptr<ItemBase> generate() { 
     return unique_ptr<ItemBase>(new Item()); 
    } 
}; 

std::unique_ptr<ItemGeneratorBase> someItem(new ItemGenerator<ItemThree>()); 
0

至於其他的答案表明,你可以使用模板實現。

只是提供另一種思路,你可以通過一個函數指針,創造任何你想要的一個實例(或者不管它是什麼,你要與該類做)

ItemGenerator(ItemClassPtr itemClassFn) 
{ 
    void * myObject = itemClassFn(); 
} 
0

我有點生疏,但我很肯定你可以在構造函數中放入ItemBase,它會接受所有的子類。

ItemGenerator::ItemGenerator(ItemBase base){\\do something with base 
} 

或者,如果使用的模板不工作,你可以創建多個構造函數:

ItemGenerator::ItemGenerator(ItemOne one){} 
ItemGenerator::ItemGenerator(ItemTwo two){} 
... 
0

你真的想通過,即一個字符串?然後,你必須提供具有相應功能的Item * - 類,例如

class ItemOne { 
    static std::string name(); 
}; 

ItemGenerator *someItem = new ItemGenerator(ItemThree::name()); 

或者,你在找的模板?你有不同的可能性有:做一個類模板,也許從ItemGenerator基類派生:

class AbstractItemGenerator { /* ... */ }; 

template <class Item> 
class ItemGenerator { 
    ItemGenerator(); 
}; 

ItemGeneratorBase *someItem = new ItemGenerator<ItemTwo>(); 

或者只使construtor模板 - 你不能顯式地指定參數,所以使用argumet扣:

//take 1: use pointers 
class ItemGenerator { 
    template <class Item> 
    ItemGenerator(Item* dummy); 
}; 

ItemGenerator *someItem = new ItemGenerator((ItemFour*)NULL); 

//take 2: use a tag struct 
template <class I> 
struct ItemTag{}; 

class ItemGenerator { 
    template <class Item> 
    ItemGenerator(ItemTag<Item> tag); 
}; 

ItemGenerator *someItem = new ItemGenerator(ItemTag<ItemOne>()); 

我不確定這些是否適合您的需求。也許要詳細說明你想用什麼。

0

這正是Factory design pattern所做的。 基本上ItemGenerator類中有一個靜態方法,它可以返回指向ItemBase對象的指針,但可以返回指向Item1,Item2等的指針,具體取決於靜態方法的參數。

例如,在ItemGenerator類,

static ItemBase *Generate(<any parameter>) 
{ 
    switch (parameter) 
    { 
     case Value1: return new Item1(); 
     ... 
     ... 
    } 
} 
0

這是很難找到一個解決問題的方法不知道的ItemGenerator目的。

由於Mankarse說,一個解決方案是使用模板類傳遞給發電機。

儘管如此,如果ItemGenerator不能被模板化,或者如果你不想在這裏使用模板,你仍然可以像使用std :: function或boost :: function一樣傳遞一個函數。

也有一些庫可以幫助您將反射添加到C++中。我記得CAMP,但我不知道它是否仍然活躍。您可以在那裏找到解決問題的方案。