我试图通过在静态地图(工厂成员)中将派生类的函数指针注册到工厂并通过查找地图来创建对象来实现工厂模式。但是我这样做会出现分段错误。
代码段:
factory.cpp
typedef Shape* (*Funcptr)();
std::map<int,Funcptr> Factory::funcmap;
int Factory::registerCreator(int ShapeID, Shape *(*CFuncptr)()) {
Factory::funcmap[ShapeID] = CFuncptr;
return 1;
}
Shape* Factory::CreateObject(int ShapeID) {
std::map<int,Funcptr>::iterator iter;
iter = funcmap.find(ShapeID);
if(iter != funcmap.end()){
return iter->second();
}
return NULL;
}
factory.h
class Factory {
public:
Factory();
virtual ~Factory();
static int registerCreator(int, Shape *(*CFuncptr)());
Shape* CreateObject(int);
private:
static std::map<int,Funcptr> funcmap;
};
Square.cpp
static Shape *SquareCreator() {
return new Square;
}
static int SquareAutoRegHook = Factory::registerCreator(1,SquareCreator);
在主文件中为Factory创建对象时,会发生分段错误。 如果我做错了,你能否建议一下?我正在使用CppUTest进行TDD而不确定如何调试它。
答案 0 :(得分:7)
无法保证在不同的翻译uint *中定义的静态对象的创建顺序,因此您有一个50/50的镜头,首先是Factory::funcmap
或{{1}的初始化和未定义的行为俄罗斯轮盘赌不是一个好玩的游戏。
处理此问题的常用方法,以及the third edition of Scott Meyer's Effective C++第4项中描述的方法是使用本地静态对象而不是全局静态对象。在这种情况下,这意味着将Factory::registerCreator(1,SquareCreator)
更改为如下所示:
Factory
并将class Factory {
public:
Factory();
virtual ~Factory();
static int registerCreator(int, Shape *(*CFuncptr)());
Shape* CreateObject(int);
private:
static std::map<int,Funcptr> & GetFactoryMap() {
static std::map<int,Funcptr> funcmap;
return funcmap;
}
};
更改为:
Factory::registerCreator
这样funcmap将在第一次调用registerCreator时初始化,永远不会被初始化。
*或者,粗略地说,如果您不熟悉术语翻译单元
,则可以使用不同的.cpp文件答案 1 :(得分:0)
看起来像static initialization order fiasco。似乎在SquareAutoRegHook
初始化时,funcmap
尚未创建。