我想知道,是否有可能在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