is it possible to return exemplar of object using passed type name (string) in c++?
I have some base abstract class Base
and 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.