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하지 않아도 되게 코드를 수정해서 해결하였다.

Posted by RPG만들기XP
,