2

I am trying to implement a FSM class and for making it more generic, I decided to use template classes; however, I am receiving some errors. The errors are not very clear (thanks to Xcode), but I think the problem is the way how I am declaring my classes and handling the inheritance, etc.

UPDATE:

Errors:

Error

Here's my code:

FiniteStateMachine.hpp

---------------------------------
template<class RETURNS, typename PARAMS>
class BaseState
{
public:
    // For forcing all the classes have this method
    virtual std::vector<RETURNS> performDecision(PARAMS& pList) = 0;
};

template<class R, typename P>
class FSM_State : public BaseState<R, P>
{
public:

    FSM_State(int pStateNum = 0);
    virtual ~FSM_State();

    void init(int pStateNum = 0);

    void addState(FSM_State<R,P>* pState);
    void addState(const int pIndex, FSM_State<R,P>* pState);

    virtual std::vector<R> performDecision(P& pList) = 0;

protected:

    std::vector<FSM_State*> mStateList;
};


OHB_DT_FSM.hpp

-----------------------------------------

class OHB_DT_FSM_State : public FSM_State<eDECISION_TYPES, GameAI>
{
public:

    OHB_DT_FSM_State(int pStateNum = 0)
        : FSM_State(pStateNum)
    {}

    virtual ~OHB_DT_FSM_State()
    {
        delete mDecisionTree;
    }

    virtual void constructDT() = 0;

    virtual std::vector<eDECISION_TYPES> performDecision(GameAI& pList) = 0;

protected:

    eSTATE_TYPES mType;

    std::vector<eDECISION_TYPES> mDecisionList;

    DecisionTree* mDecisionTree;
};

This is how I am handling the inheritance, but since I am not experienced about templates, I am not sure about my approach.

For every method that is not described in .hpp file, I have the codes in .cpp files.

CPP File:

template<class R, typename P>
FSM_State<R, P>::FSM_State(int pStateNum)
{
    init(pStateNum);
}

template<class R, typename P>
FSM_State<R, P>::~FSM_State()
{
    for(int si = 0; si < mStateList.size(); si++)
    {
        delete mStateList[si];
    }

    mStateList.clear();
}

template<class R, typename P>
void FSM_State<R, P>::init(int pStateNum)
{
    if(pStateNum > 0)
    {
        mStateList.resize(pStateNum);
    }
}

template<class R, typename P>
void FSM_State<R, P>::addState(FSM_State* pState)
{
    mStateList.push_back(pState);
}

template<class R, typename P>
void FSM_State<R, P>::addState(const int pIndex, FSM_State* pState)
{
    mStateList[pIndex] = pState;
}

Thank you!

ciyo
  • 725
  • 4
  • 16
  • 36

2 Answers2

0

Nothing in the CPP file where class FSM_state is defined triggers an instantiation of FSM_state<eDECISION_TYPES, GameAI> - the compiler has no reason to build one, so it doesn't. Then when the compiler gets to that very instantiation in OHB_DT_FSM.hpp - presumably in a different compilation unit - it no longer has access to the class definition, so it can't build that instantiation.

As other commentators have noted - one solution to this problem is to include the definition (not just the declaration) of your template class everywhere it is used - usually by putting the definition in the header. This has its advantages and disadvantages - any change to the internals of FSM_state now means that everything that depends on it has to be recompiled.

Another option is to add to your CPP file where FSM_state is defined an explicit instantiation of the type you know you will need:

template class FSM_state<eDECISION_TYPES, GameAI>;

This essentially gives the compiler the hint to instantiate the template class for those parameters, even though nothing else in the compilation unit needs that particular instantiation.

gcbenison
  • 11,723
  • 4
  • 44
  • 82
-2

When declaring a virtual function, consider the part at the end:

  • = 0; indicates a Pure-Virtual Function which means that this function has to be implemented by a deriving class
  • override; means that you are overriding a virtual function from a base class

In your example, you only use = 0; - but both FSM_State and OHB_DT_FSM_State should override your performDecision here.

Freakyy
  • 365
  • 5
  • 16