Для предстоящей курсовой работы в январе я начал разработку небольшого движка 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.
Статические члены класса должны быть предоставлены хранилище. Они как 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
возвращается.
Других решений пока нет …