根据文本文件中提供的类名创建对象?

时间:2011-03-06 03:56:37

标签: c++

我想知道,在C ++中是否可以使用从文件读入的文本值来创建该名称类的对象,例如。

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

如果可能的话,我想避免使用一系列硬编码的if / then / elses。 对不起,我不知道如何用更多技术术语来描述这个问题!

5 个答案:

答案 0 :(得分:8)

只要你不介意一些限制,这很容易做到。执行此任务的最简单方法是将您限制为从一个公共基类继承的类。在这种情况下,您可以执行以下操作:

// 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;
};

然后,您显然需要从该基础派生的一些具体类:

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; }

最后,我们需要一个从名称到工厂函数的地图:

// 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;

当然,一般主题有很多变化。例如,您可以静态地创建每个对象的实例,而不是动态创建对象的工厂函数,只需将静态对象的地址放在地图中即可。

答案 1 :(得分:1)

您可以使用抽象工厂来执行此操作。限制是需要实现基类的类,您需要使用抽象工厂注册工厂类。

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; }
   }
};

所以它应该像:

一样使用
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

的模板类来进一步优化方案

答案 2 :(得分:0)

大多数C ++框架(例如,MFC,Boost)支持某种对象序列化,尽管它通常不采用人类可读文本文件的形式。在C ++中,其实例记录在文件中的所有类类型必须存在(即编译并链接到)程序中,以便该程序能够写入或读取(并从中创建对象)这样的文件。 / p>

答案 3 :(得分:0)

使用像C ++这样的编译语言,您将无法这样做。 只有使用解释型语言才能实现这些功能,例如PHP。

答案 4 :(得分:0)

您需要的是boost serializarion。这将允许您将对象保存在文件中。您可以找到example here