Help linking a multisource project

// Need help linking. I keep getting an undefined reference
Terminal output:
[email protected]:~/workspace/AI/src$ g++ -c AI.cpp
[email protected]:~/workspace/AI/src$ g++ -c BaseGameEntity.cpp
[email protected]:~/workspace/AI/src$ g++ -c Miner.cpp
[email protected]:~/workspace/AI/src$ g++ -c State.cpp
[email protected]:~/workspace/AI/src$ g++ -c StateMachine.cpp
[email protected]:~/workspace/AI/src$ g++ AI.o BaseGameEntity.o Miner.o State.o StateMachine.o -o AI
Miner.o: In function `AI::Miner::Miner(std::string)':
Miner.cpp:(.text+0x5c): undefined reference to `AI::StateMachine<AI::Miner>::StateMachine(AI::Miner*)'
collect2: error: ld returned 1 exit status


// AI.cpp
#include "Miner.h"

int main() {
AI::Miner* miner = new AI::Miner("Miner");
miner->update();
std::cout << miner->getName() << "\n";
delete miner;
return 0;
}
// AI.cpp
--------------------------------------------------------------------
// Miner.cpp
#include "Miner.h"

namespace AI {

Miner::Miner(std::string name) :
BaseGameEntity(name)
{
m_stateMachine = new StateMachine<Miner>(this);
std::cout << "Miner constructor\n";
}
// Miner.cpp
------------------------------------------------------
// Miner.h
#ifndef MINER_H_
#define MINER_H_

#include <iostream>
#include <string>
#include "BaseGameEntity.h"
#include "StateMachine.h"

namespace AI {


class Miner : public BaseGameEntity {
private:

StateMachine<Miner>* m_stateMachine;
public:
Miner(std::string name);
virtual ~Miner();
void update();
};

} /* namespace AI */

#endif /* MINER_H_ */
// Miner.h
------------------------------------------------------
// BaseGameEntity.cpp
#include <iostream>
#include "BaseGameEntity.h"

namespace AI {
int BaseGameEntity::m_iNextValidID=0;

BaseGameEntity::BaseGameEntity(std::string name)
{
m_ID = m_iNextValidID;
m_iNextValidID++;
m_Name = name;
std::cout << "BaseGameEntity constructor\n";
}

BaseGameEntity::~BaseGameEntity() {
std::cout << "BaseGameEntity destructor\n";
}

std::string BaseGameEntity::getName() {
return m_Name;
}

} /* namespace AI */
// BaseGameEntity.cpp
----------------------------------------------------------------
// BaseGameEntity.h
#ifndef BASEGAMEENTITY_H_
#define BASEGAMEENTITY_H_

#include <string>

namespace AI {

class BaseGameEntity {
private:
int m_ID;
static int m_iNextValidID;
std::string m_Name;
public:
BaseGameEntity(std::string name);
virtual ~BaseGameEntity();
virtual void update()=0;
virtual std::string getName()=0;
};

} /* namespace AI */

#endif /* BASEGAMEENTITY_H_ */
// BaseGameEntity.h
------------------------------------------------------------
// State.cpp
#include "State.h"

namespace AI {


template <class T>
State<T>::~State() {
// TODO Auto-generated destructor stub
}

} /* namespace AI */
// State.cpp
--------------------------------------------------------------
// State.h
#ifndef STATE_H_
#define STATE_H_

namespace AI {

template <class T>
class State {
public:
virtual ~State();
virtual void enter(T* t)=0;
virtual void execute(T* t)=0;
virtual void exit(T* t)=0;
};

} /* namespace AI */

#endif /* STATE_H_ */
// State.h
----------------------------------------------------------
// StateMachine.cpp
#include "StateMachine.h"

namespace AI {

template <class T>
StateMachine<T>::StateMachine(T* owner) :
m_owner(owner),
m_currentState(NULL),
m_previousState(NULL),
m_globalState(NULL) {

}

template <class T>
StateMachine<T>::~StateMachine() {
}

template<class T>
void StateMachine<T>::setCurrentState(State<T>* state) {
m_currentState = state;
}

template<class T>
void StateMachine<T>::setPreviousState(State<T>* state) {
m_previousState = state;
}

template<class T>
void StateMachine<T>::setGlobalState(State<T>* state) {
m_globalState = state;
}

template <class T>
void StateMachine<T>::update()const {
if (m_currentState) {
m_currentState->execute(m_owner);
}
if (m_globalState) {
m_globalState->execute(m_owner);
}
}

template <class T>
void StateMachine<T>::changeState(State<T>* newState) {
if (newState) {
m_previousState = m_currentState;
m_currentState->exit(m_owner);
m_currentState = newState;
m_currentState->enter(m_owner);
}
}

template <class T>
void StateMachine<T>::revertToPreviousState() {
changeState(m_previousState);
}

} /* namespace AI */
// StateMachine.cpp
-----------------------------------------------------------
// StateMachine.h
#ifndef STATEMACHINE_H_
#define STATEMACHINE_H_

#include <cstddef>
#include "State.h"


namespace AI {

template <class T>
class StateMachine {
private:
T* m_owner;
State<T>* m_currentState;
State<T>* m_previousState;
State<T>* m_globalState;
public:
StateMachine(T* owner);
virtual ~StateMachine();
void setCurrentState(State<T>* state);
void setPreviousState(State<T>* state);
void setGlobalState(State<T>* state);
void update()const;
void changeState(State<T>* newState);
void revertToPreviousState();
};

} /* namespace AI */

#endif /* STATEMACHINE_H_ */
// StateMachine.h
As StateMachine is a template class, it should be defined in a header file, not a cpp file.

The C++ template is a code generator, and the code is generated on use. So all used parts of the template must be visible to the user at the point of use; that is, at compile time, not link time.
Yup. That worked. Thank you.
Registered users can post here. Sign in or register to post.
  • 1007451581 2018-02-22
  • 8908121580 2018-02-22
  • 141161579 2018-02-22
  • 9421578 2018-02-22
  • 2826901577 2018-02-22
  • 3647361576 2018-02-22
  • 5717551575 2018-02-22
  • 523811574 2018-02-22
  • 6439871573 2018-02-22
  • 8109431572 2018-02-22
  • 8757321571 2018-02-22
  • 5265111570 2018-02-22
  • 3351351569 2018-02-22
  • 5109361568 2018-02-22
  • 4455391567 2018-02-22
  • 9091121566 2018-02-22
  • 24791565 2018-02-22
  • 2486841564 2018-02-21
  • 9847231563 2018-02-21
  • 9264681562 2018-02-21