Create an object based on the class name provided in the text file?

I am wondering if it is possible in C ++ to use a text value read from a file to create a class object of that name, for example.

contents of file: "MyClass"
code: read file
code: instantiate "MyClass" object.

I would like to avoid a whole series of hard-coded if / then / elses if possible. Sorry, I'm not sure how to describe this problem more technically!

+3
source share
5 answers

As long as you don't mind some restrictions, it's pretty easy to do. The easiest way to complete the task limits you to classes that come from one common base class. In this case, you can do something like this:

// warning: I've done this before, but none of this code is tested. The idea 
// of the code works, but this probably has at least a few typos and such.
struct functor_base { 
    virtual bool operator()() = 0;
};

Then, obviously, you will need some specific classes derived from this base:

struct eval_x : functor_base { 
   virtual bool operator()() { std::cout << "eval_x"; }
};

struct eval_y : functor_base {
    virtual bool operator()() { std::cout << "eval_y"; }
};

- :

functor_base *create_eval_x() { return new eval_x; }
functor_base *create_eval_y() { return new eval_y; }

, factory:

// the second template parameter is:
// pointer to function returning `functor_base *` and taking no parameters.
std::map<std::string, functor_base *(*)()> name_mapper;

name_mapper["eval_x"] = create_eval_x;
name_mapper["eval_y"] = create_eval_y;

(!) , :

char *name = "eval_x";

// the map holds pointers to functions, so we need to invoke what it returns 
// to get a pointer to a functor:
functor_base *b = name_mapper.find(name)();

// now we can execute the functor:
(*b)();

// since the object was created dynamically, we need to delete it when we're done:
delete b;

, , . , factory , , .

+8

factory . - , , factory factory.

class AbstractFactory;
class Factory;
class Object;

// base marker class for all the classes that need this instantiation strategy
class Object{}

class Factory
{
public:
   //override this in concrete factories
   virtual Object* create() = 0;
};
// helper macro to declare an inner class that a default factory
#define DECL_DEFAULT_FACTORY(ObjectClass) class Factory : public Factory \
{\
public:\
   Factory(){}\
   virtual ~Factory(){}\
   Object* create(){ return new ObjectClass(); } \
}
// this can be made a singleton
class AbstractFactory
{
public:
   void registerClass(const String& clsName, Factory* factory){ //put this in a std::map }
   void deregisterClass(const String& className){ //remove factory from map and delete the ptr }
   Object* create(const String& className)
   {
     Factory* factory = factories[className];
     if(factory){ return factory->create(); }
     else{ return 0; }
   }
};

:

class SampleClass : public Object
{ 
//impl goes here 
DECL_DEFAULT_FACTORY(SampleClass);
}

-

abstractFactoryInstance->registerClass("SampleClass",new SampleClass::Factory());

AbstractFactory

SampleClass* obj = (SampleClass*)(abstractFactoryInstance->create("SampleClass"));

, Factory

+1

++ (, MFC, Boost) - , , . ++ , , (.. ) , , ( ) .

0

, ++, . , PHP.

0

, . . .

0
source

Source: https://habr.com/ru/post/1796585/


All Articles