静态成员初始化链接错误

时间:2012-11-28 13:39:16

标签: c++ templates static

对于即将开始的课程,我试图避免虚拟,看看我是否可以挤出更高的性能/内存效率。当我想要实现StateManager时,问题就出现了(课程原型是一个小游戏)。

为了实现这一点,我有一个模板来“statif”当前状态的成员函数调用。

一个示例状态是:

struct TestState {
    bool update(float delta) {
        return true;
    }
};

现在,状态管理器应该能够接受任何State-Class并绑定更新功能。 使用boost :: bind和boost :: function很容易实现这一点,但是与虚拟相比,性能有所下降,所以我想看看是否有可能没有提升。

理论上,如果State是一个只包含静态函数的类/结构,那么这将很容易,但这也增加了不灵活性和更多的静态初始化混乱。

StateManager当前版本是:

 class StateManager
 {
 public:
     template <typename S> static void set(S* state)
     {
         #define UPDATE_ID 0

         StateFunctionHandler<UPDATE_ID, S, bool, float>::bind(std::mem_fun1(&S::update), state);
         m_funcUpdate = StateFunctionHandler<UPDATE_ID, S, bool, float>::exec;
     }
     static bool update(float delta) 
     {
         return m_funcUpdate(delta);
     }
     typedef bool (*funcUpdate)(float);
 private:   
     static funcUpdate m_funcUpdate;
 };

StateFunctionHandler是负责将成员函数包装在StateFunctionHandler的静态成员中的模板。模板的第一个参数是一个ID,用于强制多个模板用于具有相同返回类型和参数的函数。

在代码中它看起来像这样:

template <int ID, typename S, typename R, typename A>
struct StateFunctionHandler 
{ 
    static void bind(std::mem_fun1_t<R, S, A> f, S* s)
    {
        func = f;
        pState = s;
    } 
    static R exec(A arg) 
    { 
        return func(pState, arg); 
    } 

    static std::mem_fun1_t<R, S, A> func; 
    static S* pState; 
};

现在的问题是为使用的情况初始化StateFunctionHandler的模板化静态成员,因为我们需要强制编译器初始化它们。

在这些类的关联cpp文件中,静态成员被初始化:

template <int ID, typename S, typename R, typename A> std::mem_fun1_t<R, S, A> StateFunctionHandler<ID, S, R, A>::func;
template <int ID, typename S, typename R, typename A> S* StateFunctionHandler<ID, S, R, A>::pState = NULL;

StateManager::funcUpdate StateManager::m_funcUpdate = NULL;

但是我收到StateFunctionHandler :: func和:: pState的链接错误(LNK2001),因此编译器似乎没有初始化StateFunctionHandler的静态成员。

用例:

 TestState* t = new TestState();
 StateManager::set(t);
 StateManager::update(0.1f);

再说一遍,我不想使用boost,这是一个实验,看看我是否可以在这个用例中避免虚函数并且也有性能。

1 个答案:

答案 0 :(得分:1)

您应该将静态模板类成员的初始化移动到头文件中。

它应该在每个实例化模板的翻译单元中可见,与非静态模板类成员相同。