C++에서 보통은 헤더파일에는 외부 클래스를 전방선언만 해두고, .cpp파일에서 구현부를 가져다 쓰는 것이 일반적이다.(순환참조를 막기 위해)
헌데 템플릿 멤버함수를 선언하려니, 템플릿 함수는 구현부와 선언부를 헤더와 cpp파일에 분리할 수 없다.(어쩌고 저쩌고 사정으로 인해.)
따라서 전방선언해둔 클래스의 기능을 실제로 호출하는 코드를 헤더에 정의하게 되는데, 비주얼스튜디오는 알아서 잘 컴파일해주지만, 몇몇 컴파일러에서는 깐깐하게도 "정의는 없고 선언만 있는 클래스인데 멤버함수를 호출하셨네요! 컴파일 못해요!" 해버린다.
어떻게 해결해야 할까..
#pragma once class UnitState; //Unit 자식 클래스를 위한 CREATE_FUNC #define CREATE_FUNC_UNIT(__TYPE__) \ static __TYPE__* create(PLAYER_KIND ownerPlayer) \ { \ __TYPE__ *pRet = new(std::nothrow) __TYPE__(); \ if (pRet && pRet->init(ownerPlayer)) \ { \ pRet->autorelease(); \ pRet->scheduleUpdate();\ return pRet; \ } \ else \ { \ delete pRet; \ pRet = nullptr; \ return nullptr; \ } \ } class Unit : public Sprite { public: bool init(PLAYER_KIND playerKind); CREATE_FUNC_UNIT(Unit) virtual void update(float delta); template<typename T_STATE> void changeState() { if (_state) { this->getState()->EndState(this); this->removeComponent(_state); } auto state = T_STATE::create(); this->setState(state); this->getState()->StartState(this);//문제가 되는 부분. 선언만 해놓은 클래스(UnitState)의 구현부를 가져다 쓰고 있다. this->addComponent(state); } CC_SYNTHESIZE(UnitState*, _state, State); CC_SYNTHESIZE(std::string, _unitName, UnitName); CC_SYNTHESIZE(float, _attackRange, AttackRange); CC_SYNTHESIZE(float, _attackSpeed, AttackSpeed); CC_SYNTHESIZE(float, _moveSpeed, MoveSpeed); CC_SYNTHESIZE(Unit*, _attackTarget, AttackTarget); CC_SYNTHESIZE_READONLY(PLAYER_KIND, _ownerPlayer, OwnerPlayer); Unit* scanNearestTarget(); private: };
ㄴ 문제의 코드.
공부좀 해보고 해결하면 다시 정리해서 올려야겠다.
* 일단은 문제의 UnitState.h에서 Unit.h를 include하지 않아도 되게 코드를 수정해서 해결하였다.
'C++' 카테고리의 다른 글
shared_from_this()는 생성자 안에서 호출하면 안된다. (0) | 2016.10.12 |
---|---|
데이터 시리얼라이즈 라이브러리 MsgPack에 대해 정리해 보았다. (0) | 2016.05.16 |