Частичные проблемы вызова приложений

Для предстоящей курсовой работы в январе я начал разработку небольшого движка DirectX. Чтобы выяснить, есть ли повышение производительности, я хотел попытаться вообще не использовать виртуалы (я знаю, что виртуалы не так уж и плохи, но я просто хотел посмотреть, возможно ли это без них).

Когда я начал играть с простым StateManager, мне было трудно избегать виртуалов, но это мой текущий подход:

#include <boost\function.hpp>
#include <boost\bind.hpp>

template <class Derived>
struct TBaseState {
  bool update(float delta) {
    return static_cast<Derived *>(this)->update(delta);
  };
};

struct CTestState : TBaseState<CTestState> {
  bool update(float delta) {
      return true;
  }
};

class StateManager
{
public:
    template <class StateClass> static void setState(StateClass nextState)
    {
        m_funcptrUpdate = boost::bind(&TBaseState<StateClass>::update,     boost::ref(nextState), _1);
    }
    static bool update(float delta) 
    {
        return m_funcptrUpdate(delta);
    }
protected:
private:
    static boost::function<bool (float)> m_funcptrUpdate;
};

Intellisense в Visual Studio 2010, кажется, считает, что все в порядке, но когда я хочу скомпилировать программу и протестировать StateManager с очень простым подходом:

CTestState* t = new CTestState(); 
StateManager::setState(*t);
StateManager::update(0.0f);

Следующая ошибка выдается на этапе компоновки:

error LNK2001: unresolved external symbol "private: static class boost::function<bool __cdecl(float)> StateManager::m_funcptrUpdate" (?m_funcptrUpdate@StateManager@@0V?$function@$$A6A_NM@Z@boost@@A)

Очевидно, он не может найти связанную функцию, но как я могу решить эту проблему? Я получаю похожие ошибки, если использую boost::bind напрямую к какому-либо классу. Поскольку я студент информатики, меня также могут заинтересовать некоторые идеи или подходы без повышения (например, bind1st,...).

РЕДАКТИРОВАТЬ: Я также думал об использовании C++11 Variadic Templates, но одно из требований курсовой работы является придерживаться VS2012.

1 ответ

Решение

Статические члены класса должны быть предоставлены хранилище. Они как extern переменные. Добавьте определение к одному из ваших .cpp файлы вне определения класса:

boost::function<bool (float)> StateManager::m_funcptrUpdate;

Также в этом коде:

template <class StateClass> static void setState(StateClass nextState)
{
    m_funcptrUpdate = boost::bind(&TBaseState<StateClass>::update,
        boost::ref(nextState), _1);
}

Вы сохраняете хранение ссылки на локальную переменную nextState, Эта ссылка будет недействительной после setState возвращается.

Другие вопросы по тегам