从静态成员函数访问静态映射 - 分段错误 - C++

Saa*_*ras 5 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;
}
Run Code Online (Sandbox Code Playgroud)

factory.h

class Factory {
public:
    Factory();
    virtual ~Factory();
    static int registerCreator(int, Shape *(*CFuncptr)());
    Shape* CreateObject(int);
private:
    static  std::map<int,Funcptr> funcmap;
};
Run Code Online (Sandbox Code Playgroud)

Square.cpp

static Shape *SquareCreator() { 
    return new Square; 
}
static int SquareAutoRegHook = Factory::registerCreator(1,SquareCreator);
Run Code Online (Sandbox Code Playgroud)

在主文件中为Factory创建对象时,会发生分段错误.如果我做错了,你能否建议一下?我正在使用CppUTest进行TDD而不确定如何调试它.

Iro*_*san 7

无法保证在不同的翻译uint*中定义的静态对象的创建顺序,所以你有50/50的镜头关于哪个会先发生,初始化Factory::funcmapFactory::registerCreator(1,SquareCreator)未定义的行为俄罗斯轮盘不是一个好的游戏玩.

处理此问题的常用方法,以及Scott Meyer的Effective C++第3版第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;
    } 
}; 
Run Code Online (Sandbox Code Playgroud)

Factory::registerCreator改为:

int Factory::registerCreator(int ShapeID, Shape *(*CFuncptr)()) {   
    GetFactoryMap()[ShapeID] = CFuncptr;   
    return 1;   
}
Run Code Online (Sandbox Code Playgroud)

这样,funcmap将在第一次调用registerCreator时初始化,永远不会被初始化.

*或者,粗略地说,如果您不熟悉术语翻译单元,则可以使用不同的.cpp文件