Create object based on class name provided in text file?
I'm wondering, is it possible in C++ to use a text value read in from a file to create an object of a class of that name eg.
contents of file: "MyClass"
code: read file
code: instantiate "MyClass" object.
I'd like to avoid a whole series of hardcoded if/then/elses if poss开发者_Python百科ible. Sorry I'm not sure how to describe this problem in more technical terms!
As long as you don't mind some restrictions, this is fairly easy to do. The easiest way to do the job restricts you to classes that descend 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;
};
You'll then obviously need some concrete classes derived from that 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"; }
};
Then we need some way to create an object of each type:
functor_base *create_eval_x() { return new eval_x; }
functor_base *create_eval_y() { return new eval_y; }
Finally, we need a map from the names to the factory functions:
// 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;
That (finally!) gives us enough so we can map from a name to a function object:
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;
There are, of course, many variations on the general theme. For example, instead of factory functions that create objects dynamically, you can create an instance of each object statically, and just put the address of the static object in the map.
you can use abstract factory to do this. Limitations are the classes need to implement a base class and you need to register the factory class with the abstract 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's 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; }
}
};
so it shall be used like:
class SampleClass : public Object
{
//impl goes here
DECL_DEFAULT_FACTORY(SampleClass);
}
and somewhere else you need to do
abstractFactoryInstance->registerClass("SampleClass",new SampleClass::Factory());
then your AbstractFactory is ready to do
SampleClass* obj = (SampleClass*)(abstractFactoryInstance->create("SampleClass"));
you can further refine the scheme by declaring template classes for Factory
Most C++ frameworks (e.g., MFC, Boost) support some kind of object serialization, though it doesn't generally take the form of a human-readable text file. In C++, all of the class types whose instances are recorded in a file have to be present (i.e., compiled and linked into) a program in order for that program to either write or read (and create objects from) such a file.
With Compiled languages like C++, you won't be able to do so. Such things are only possible with interpreted languages, such as PHP.
What you need is boost serializarion. This will allow you to persist your objects in a file. You can find an example here.
精彩评论