爲什麼下面的代碼引發異常(在createObjects來電map::at
) alternativly代碼(及其輸出)可以被看作here(靜態初始化/模板實例化)問題與工廠模式
intererestingly的代碼工作預計如果註釋行不用微軟和gcc編譯器註釋(見here),甚至可以使用initMap作爲普通靜態變量而不是靜態獲取器。
爲了這個,我能想到的唯一原因是,靜態registerHelper_對象(factory_helper_
)和std::map
對象(initMap
)是錯誤的初始化命令,但是我看不到怎麼會發生,因爲地圖對象是建立在第一次使用和那在factory_helper_構造函數,所以一切都應該沒問題呢? 我更加驚訝的是,那些沒有()行修復了這個問題,因爲那個調用doNothing()會在臨界區(當前失敗)之後發生。
編輯:調試顯示,沒有調用factory_helper_.doNothing(),factory_helper_的構造函數永遠不會被調用。
#include <iostream>
#include <string>
#include <map>
#define FACTORY_CLASS(classtype) \
extern const char classtype##_name_[] = #classtype; \
class classtype : FactoryBase<classtype,classtype##_name_>
namespace detail_
{
class registerHelperBase
{
public:
registerHelperBase(){}
protected:
static std::map<std::string, void * (*)(void)>& getInitMap() {
static std::map<std::string, void * (*)(void)>* initMap = 0;
if(!initMap)
initMap= new std::map<std::string, void * (*)(void)>();
return *initMap;
}
};
template<class TParent, const char* ClassName>
class registerHelper_ : registerHelperBase {
static registerHelper_ help_;
public:
//void doNothing(){}
registerHelper_(){
getInitMap()[std::string(ClassName)]=&TParent::factory_init_;
}
};
template<class TParent, const char* ClassName>
registerHelper_<TParent,ClassName> registerHelper_<TParent,ClassName>::help_;
}
class Factory : detail_::registerHelperBase
{
private:
Factory();
public:
static void* createObject(const std::string& objclassname) {
return getInitMap().at(objclassname)();
}
};
template <class TClass, const char* ClassName>
class FactoryBase {
private:
static detail_::registerHelper_<FactoryBase<TClass,ClassName>,ClassName> factory_helper_;
static void* factory_init_(){ return new TClass();}
public:
friend class detail_::registerHelper_<FactoryBase<TClass,ClassName>,ClassName>;
FactoryBase(){
//factory_helper_.doNothing();
}
virtual ~FactoryBase(){};
};
template <class TClass, const char* ClassName>
detail_::registerHelper_<FactoryBase<TClass,ClassName>,ClassName> FactoryBase<TClass,ClassName>::factory_helper_;
FACTORY_CLASS(Test) {
public:
Test(){}
};
int main(int argc, char** argv) {
try {
Test* test = (Test*) Factory::createObject("Test");
}
catch(const std::exception& ex) {
std::cerr << "caught std::exception: "<< ex.what() << std::endl;
}
#ifdef _MSC_VER
system("pause");
#endif
return 0;
}
將一些調試打印添加到您的構造函數和訪問函數中,查看哪些對象正在創建以及何時。 – 2010-05-17 19:48:38