我想知道,是否有可能在C++中使用从文件中读取文本值来创建一个类,名称,如的对象。根据文本文件中提供的类名创建对象?
contents of file: "MyClass"
code: read file
code: instantiate "MyClass" object.
我想避免一系列硬编码if/then/elses如果可能的话。 对不起,我不知道如何在更多的技术术语描述这个问题!
我想知道,是否有可能在C++中使用从文件中读取文本值来创建一个类,名称,如的对象。根据文本文件中提供的类名创建对象?
contents of file: "MyClass"
code: read file
code: instantiate "MyClass" object.
我想避免一系列硬编码if/then/elses如果可能的话。 对不起,我不知道如何在更多的技术术语描述这个问题!
大多数C++框架(例如,MFC,升压)支持某种对象序列化,尽管它通常不采取人类可读的文本文件的形式。在C++中,所有的类类型,其实例被记录在一个文件必须存在(即,编译并链接到)中的程序,以便该程序的写或读(和创建对象)这样的文件名。
有了这样C++编译语言,你将不能够这样做。 这样的事情只与解释的语言,如PHP可能。
只要你不介意一些限制,这是相当容易的事。做这项工作最简单的方法是限制你从一个共同基类中下来的类。在这种情况下,你可以做这样的事情:
// 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;
有,当然,对一般的主题很多变化。例如,而不是动态创建对象的工厂功能,您可以创建每个对象静态的实例,只是把静态对象的地址在地图中。
我......暂时无法决定是为了聪明还是为了同样的原因而低估它。 :-) – ceo 2011-03-06 04:47:10
@ceo:嗯......我不认为它特别“聪明” - 只是一个相当普通的数据结构从名称映射到功能的简单应用。在写一些像翻译这样的东西时,这很常见 - 这似乎只是一种有限的解释形式。 – 2011-03-06 05:02:11
你需要的是boost serializarion。这将允许你将你的对象保存在一个文件中。你可以找到一个example here。
您可以使用抽象工厂来做到这一点。限制是需要实现基类的类,并且您需要向抽象工厂注册工厂类。
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);
}
和别的地方,你需要做的
那么你AbstractFactory是准备做
SampleClass* obj = (SampleClass*)(abstractFactoryInstance->create("SampleClass"));
你可以进一步完善计划通过宣布模板类为工厂
...不可能我的知识。任何你想要类似的理由? – quasiverse 2011-03-06 03:57:46
嗯....好像看起来可能不是一个好手。我想要在计算成本时在程序中使用的配置文件中指定一个成本函数。 – 2011-03-06 04:05:25
好吧,如果你想在你的文件中的实际代码,然后忽略我的答案。事实上,这不是一个好人。 – Jollymorphic 2011-03-06 04:26:10