Activating a class by class name

I have several classes that have a common base class, for example:

class Base {};

class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};

Now I need to know which of these derived classes need to be created at runtime (based on input). For example, if input "DerivedA", I need to create an object DerivedA. Input is not necessarily a string; it can be an integer. The fact is that there is some key, and I need a value corresponding to the key.

The problem is, how do I instantiate a class? C ++ does not have a built-in reflection such as C # or Java. A commonly suggested solution is to use the factory method as follows:

Base* create(const std::string& name) {
    if(name == "DerivedA") return new DerivedA();
    if(name == "DerivedB") return new DerivedB();
    if(name == "DerivedC") return new DerivedC();
}

, , , , , . , std::map<std::string, ***>, , . AFAIK, . , factory, , factory , , .

, ?

+4
3

std::function<Base*()>, Base create:

class Base {};

class DerivedA : public Base {};
class DerivedB : public Base {};
class DerivedC : public Base {};

Base* create(const std::string& type)
{
    static std::map<std::string, std::function<Base*()>> type_creator_map =
    {
        {"DerivedA", [](){return new DerivedA();}},
        {"DerivedB", [](){return new DerivedB();}},
        {"DerivedC", [](){return new DerivedC();}}
    };

    auto it = type_creator_map.find(type);
    if(it != type_creator_map.end())
    {
        return it->second();
    }

    return nullptr;
}

, std::unique_ptr . create std::shared_ptr, "" .

UPDATE:

.

, ( ), ( , , ), main() .

, , , , !

class Base {};

std::map<std::string, std::function<Base*()>>& get_type_creator_map()
{
    static std::map<std::string, std::function<Base*()>> type_creator_map;
    return type_creator_map;
}

template<typename T>
struct RegisterTypeHelper
{
    RegisterTypeHelper(const std::string& id)
    {
        get_type_creator_map()[id] = [](){return new T();};
    }
};

Base* create(const std::string& type)
{
    auto& type_creator_map = get_type_creator_map();
    auto it = type_creator_map.find(type);
    if(it != type_creator_map.end())
    {
        return it->second();
    }

    return nullptr;
}

#define RegisterType(Type) static RegisterTypeHelper<Type> register_type_global_##Type(#Type)

class DerivedA : public Base {};
RegisterType(DerivedA);

class DerivedB : public Base {};
RegisterType(DerivedB);

class DerivedC : public Base {};
RegisterType(DerivedC);
+7

- Prototype.

, , . create() Factory. Prototype , :

class Base
{
public:
  virtual ~Base() {}
  virtual Base* clone() = 0;
};

class DerivedA : public Base
{
public:
  virtual DerivedA* clone() override { return new DerivedA; }
};


Base* create(const std::string &name)
{
  static std::map<std::string, Base*> prototypes {
    { "DerivedA", new DerivedA },
    { "DerivedB", new DerivedB },
    { "DerivedC", new DerivedC }
  };
  return prototypes[name]->clone();
}

.

, , (, std::unique_ptr) .

+3

std:: map, , .

factory , . , :

class Base {};

class DerivedA : public Base {
public:
    static Base* create();

    ...
}

...

Base* DerivedA::create() {
    return new DerivedA();
}

/ ,

typedef Base* (*FACTORY_FUNCTION)();
std::map<std::string, FACTORY_FUNCTION> factories;

...

factories["ClassA"] = ClassA::create;

factory, , factory

factory , (, script). , (, grep ping class , , - , ).

factory . , , .

+1
source

All Articles