简体   繁体   English

C ++-使用类名作为函数参数

[英]C++ - Use Class Name As Function Parameter

Say I have list of of classes called ItemOne, ItemTwo, ItemThree and ItemFour, which are all subclasses of ItemBase. 说我有一个叫做ItemOne,ItemTwo,ItemThree和ItemFour的类的列表,它们都是ItemBase的子类。

I would like to have a constructor in another class called ItemGenerator that accepts the name of any of these classes. 我想在另一个名为ItemGenerator的类中有一个构造函数,该构造函数可以接受任何这些类的名称。 How would I do this? 我该怎么做?

ItemGenerator *someItem = new ItemGenerator(ItemThree);

Another option would be to pass a static function on one of these classes, but again, I have no idea how to do that. 另一种选择是在这些类之一上传递静态函数,但是同样,我也不知道如何执行该操作。

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

Thanks. 谢谢。

You could use a template: 您可以使用模板:

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>());

Function cannot accept name of a class as a parameter, as class is not an object in C++. 函数不能接受类的名称作为参数,因为类不是C ++中的对象。 But template-function can be parametrized by a class name. 但是模板功能可以通过类名进行参数设置。

Something like this: 像这样:

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

ItemGenerator *someItem = ItemGeneratorFactory<ItemThree>();

As the other answers indicate, you can achieve using templates. 如其他答案所示,您可以使用模板。

Just to offer another idea, you can pass a function pointer that creates an instance of whatever you want (or whatever it is you want to do with that class) 为了提供另一个想法,您可以传递一个函数指针,该指针创建一个您想要的任何实例(或您想要对该类执行的任何操作)的实例

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

I'm a little rusty, but I'm pretty sure you could just put ItemBase in the constructor and it would accept all subclasses. 我有些生疏,但是我很确定您可以将ItemBase放在构造函数中,并且它将接受所有子类。

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

or, if that and using a template don't work, you could create multiple constructors: 或者,如果这样做并使用模板不起作用,则可以创建多个构造函数:

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

Do you really want to pass the name , ie a string? 您真的要传递名称 (即字符串)吗? Then you'd have to provide the Item*-classes with a corresponding function, eg 然后,您必须为Item * -class提供相应的功能,例如

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

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

Or are you looking for templates? 还是您正在寻找模板? You have different possibilities there: make a class template, maybe derived from an ItemGenerator base class: 您在那里有不同的可能性:创建一个类模板,可能是从ItemGenerator基类派生的:

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

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

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

Or make only the construtor templated - you cannot explicitly specify the parameter, so use argumet deduction: 或者仅使构造函数模板化-无法显式指定参数,因此请使用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>());

I am not sure if one of these suits your needs. 我不确定其中之一是否适合您的需求。 Maybe elaborate what you want to use this for. 也许详细说明您要使用此功能。

This is exactly what the Factory design pattern does. 这正是Factory设计模式所要做的。 Basically there is a static method in the ItemGenerator class that can return pointers to ItemBase objects, but can return pointers to Item1, Item2 etc depending on the parameters to the static method. 基本上,ItemGenerator类中有一个静态方法,该方法可以返回指向ItemBase对象的指针,但是可以根据静态方法的参数返回指向Item1,Item2等的指针。

For instance, in the ItemGenerator class, 例如,在ItemGenerator类中,

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

It is difficult to find a solution to your problem without knowing the purpose of ItemGenerator . 在不知道ItemGenerator的目的的情况下,很难找到解决问题的ItemGenerator

As Mankarse says, one solution would be to use a template to pass your class to the generator. 正如曼卡斯(Mankarse)所说,一种解决方案是使用模板将您的类传递给生成器。

Nevertheless, if ItemGenerator cannot be templated or if you do not want to use the templates here, you can still pass a function as you suggest by using either std::function or boost::function. 但是,如果无法将ItemGenerator模板化,或者如果您不想在此处使用模板,则仍可以按照建议使用std :: function或boost :: function传递函数。

There are also some libraries that can help you to add reflexion to c++. 还有一些库可以帮助您向C ++添加反射。 I remember of CAMP but I do not know if it is still active. 我记得CAMP,但不知道它是否仍在运行。 You may find a solution for your problem there. 您可能在那里找到解决问题的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM