从静态成员函数访问静态映射 - 分段错误 - C++
问题描述:
我想通过注册派生类的函数指针到工厂在静态映射(工厂的成员)和创建对象的工厂模式实现查找地图。但是我在这样做时遇到了分段错误。从静态成员函数访问静态映射 - 分段错误 - C++
代码段:
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);
在主创建对象工厂文件分段发生故障。 你可以请建议,如果我做错了什么。我正在使用CppUTest进行TDD,不知道如何调试。
答
无法保证静态对象的创建顺序,这些静态对象在不同的翻译版本中定义,因此您有50/50镜头,哪一个会先发生,Factory::funcmap
或Factory::registerCreator(1,SquareCreator)
的初始化和未定义的行为Russian Roulette是不是一个好玩的游戏。
解决这个问题的一种常用方法,以及the third edition of Scott Meyer's Effective C++第4项中描述的方法是使用本地静态对象而不是全局静态对象。在这种情况下,它意味着改变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
这样:
int Factory::registerCreator(int ShapeID, Shape *(*CFuncptr)()) {
GetFactoryMap()[ShapeID] = CFuncptr;
return 1;
}
这样funcmap将被初始化首次registerCreator被调用,绝不会被用来初始化。
*或者,如果你不familar与术语翻译单元
粗略地讲,不同的.cpp文件显示为'Funcptr' typedef的。你可以重写你的代码,以便在任何地方使用typedef(和测试)吗?另外,为什么'SquareCreator()'声明'静态'? –
@KerrekSB:依然没有变化。 – Saaras
无关紧要的是,如果函数指针总是兼容的话,我现在还不确定。我只是试图自己测试这个,而我刚刚得到了一个“无法转换”的错误。 –