开发者

Make object by its name

开发者 https://www.devze.com 2023-02-04 18:58 出处:网络
is it possible to return exemplar of object using passed type name (string) in c++? I have some base abstract class Base an开发者_C百科d a few derivates. Example code:

is it possible to return exemplar of object using passed type name (string) in c++? I have some base abstract class Base an开发者_C百科d a few derivates. Example code:

class Base
{
   /* ... */
};

class Der1 : public Base
{
   /* ... */
};

class Der2 : public Base
{
   /* ... */
};

And I need function like:

Base *objectByType(const std::string &name);

Number of derivates classes are changeable and I don't want to make something like switching of name and returning by hands new object type. Is it possible in c++ to do that automatically anyway?

p.s. usage should looks like:

dynamic_cast<Der1>(objectByType("Der1"));

I need pure c++ code (crossplatform). Using boost is permissible.


There is a nice trick which allows you to write a factory method without a sequence of if...else if....

(note that, AFAIK, it is indeed not possible to do what you want in C++ as this code is generated in the compile time. A "Factory Method" Design Pattern exists for this purpose)

First, you define a global repository for your derived classes. It can be in the form std::map<std::string, Base*>, i.e. maps a name of the derived class to an instance of that class.

For each derived class you define a default constructor which adds an object of that class to the repository under class's name. You also define a static instance of the class:

// file: der1.h
#include "repository.h"

class Der1: public Base {
public:
  Der1() { repository[std::string("Der1")] = this; }
};

// file: der1.cpp
static Der1 der1Initializer;

Constructors of static variables are run even before main(), so when your main starts you already have the repository initialized with instances of all derived classes.

Your factory method (e.g. Base::getObject(const std::string&)) needs to search the repository map for the class name. It then uses the clone() method of the object it finds to get a new object of the same type. You of course need to implement clone for each subclass.

The advantage of this approach is that when you are adding a new derived class your additions are restricted only to the file(s) implementing the new class. The repository and the factory code will not change. You will still need to recompile your program, of course.


It's not possible to do this in C++.

One options is to write a factory and switch on the name passed in, but I see you don't want to do that. C++ doesn't provide any real runtime reflection support beyond dynamic_cast, so this type of problem is tough to solve.


Yes that is possible! Check this very funny class called Activator You can create everything by Type and string and can even give a List of parameters, so the method will call the appropriate constructor with the best set of arguments.


Unless I misunderstood, the typeid keyword should be a part of what you are looking for.


It is not possible. You have to write the objectByType function yourself:

Base* objectByType(const std::string& name) {
  if (name == "Der1")
    return new Der1;
  else if (name == "Der2")
    return new Der2;
  // other possible tests
  throw std::invalid_argument("Unknown type name " + name);
}


C++ doesn't support reflection.

In my opinion this is the single point where Java beats C++.
(ope not to get too many down votes for this...)

You could achieve something like that by using a custom preprocessor, similar to how MOC does for Qt.

0

精彩评论

暂无评论...
验证码 换一张
取 消