假设我有名为ItemOne,ItemTwo,ItemThree和ItemFour的类列表,它们都是ItemBase的子类。
我想在另一个名为ItemGenerator的类中有一个构造函数,它接受任何这些类的名称。我该怎么做?
ItemGenerator *someItem = new ItemGenerator(ItemThree);
另一种选择是在其中一个类上传递静态函数,但同样,我不知道如何做到这一点。
ItemGenerator *someItem = new ItemGenerator(ItemOne::start());
感谢。
答案 0 :(得分: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>());
答案 1 :(得分:0)
函数不能接受类的名称作为参数,因为类不是C ++中的对象。 但模板函数可以通过类名进行参数化。
这样的事情:
template<class T>
ItemGenerator* ItemGeneratorFactory() { T::start(); ...}
ItemGenerator *someItem = ItemGeneratorFactory<ItemThree>();
答案 2 :(得分:0)
正如其他答案所示,您可以使用模板。
只是为了提供另一个想法,你可以传递一个函数指针来创建你想要的任何实例(或者你想用该类做什么)
ItemGenerator(ItemClassPtr itemClassFn)
{
void * myObject = itemClassFn();
}
答案 3 :(得分:0)
我有点生疏,但我很确定你可以将ItemBase
放在构造函数中,它会接受所有子类。
ItemGenerator::ItemGenerator(ItemBase base){\\do something with base
}
或者,如果它和使用模板不起作用,您可以创建多个构造函数:
ItemGenerator::ItemGenerator(ItemOne one){}
ItemGenerator::ItemGenerator(ItemTwo two){}
...
答案 4 :(得分:0)
你真的想传递名称,即字符串吗?然后你必须为Item * -classes提供相应的函数,例如
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>();
或者只让构造者模板化 - 你不能明确指定参数,所以使用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>());
我不确定其中一个是否符合您的需求。也许详细说明你想用它来做什么。
答案 5 :(得分:0)
这正是Factory design pattern所做的。 基本上,ItemGenerator类中有一个静态方法可以返回指向ItemBase对象的指针,但是可以返回指向Item1,Item2等的指针,具体取决于静态方法的参数。
例如,在ItemGenerator类中,
static ItemBase *Generate( <any parameter> )
{
switch (parameter)
{
case Value1: return new Item1();
...
...
}
}
答案 6 :(得分:0)
如果不了解ItemGenerator
的目的,很难找到问题的解决方案。
正如Mankarse所说,一种解决方案是使用模板将您的类传递给生成器。
然而,如果ItemGenerator
无法模板化或者您不想在此处使用模板,您仍然可以使用std :: function或boost :: function传递一个函数。
还有一些库可以帮助您为c ++添加反射。我记得CAMP,但我不知道它是否仍然有效。您可以在那里找到解决问题的方法。