I’m getting some really wierd linking errors from a class I wrote. I am completely unable to find anything that will describe what is happening.
Visual Studio (Windows XP)
players.obj : error LNK2019: unresolved external symbol ‘public: __thiscall TreeNode::TreeNode(void)’ (??0?$TreeNode@VPlayer@@@@QAE@XZ) referenced in function ‘public: __thiscall PlayerList::PlayerList(void)’ (??0PlayerList@@QAE@XZ)
Xcode (OSX 10.5)
Undefined symbols: ‘TreeNode::~TreeNode()’, referenced from: PlayerList::~PlayerList()in players.o
Header File: generics.h
class TreeNode : public BaseNode{ public: const static int MAX_SIZE = -1; //-1 means any size allowed. const static int MIN_SIZE = 0; //getters int size() const; vector<C*> getChildren() const; //setters void setChildren(vector<C*> &list); //Serialization virtual void display(ostream &out) const; virtual void read(istream &in); virtual void write(ostream &out) const; //Overrides so SC acts like an array of sorts. virtual C* get(int id) const; virtual int get(C *child) const; virtual bool has(C *child) const; virtual C* pop(int id); virtual void push(C *child); virtual TreeNode& operator<< (C *child); //append virtual void remove(int id); //Clears memory virtual void remove(C *child); //Clears memory //Initalizers TreeNode(); TreeNode(istream &in); TreeNode(long id, istream &in); TreeNode(BaseNode* parent, istream &in); TreeNode(long id, BaseNode* parent); TreeNode(long id, BaseNode* parent, istream &in); ~TreeNode(); string __name__() const{ return 'TreeNode'; } protected: void clearChildren(); void initalizeChildren(); vector<C*> _children; };
Code from a subclass of TreeNode
PlayerList::PlayerList() : TreeNode<Player>(){} PlayerList::PlayerList(istream &in) : TreeNode<Player>(in){} PlayerList::~PlayerList(){}
When you define your template in a .cpp file, you have to explicitly instantiate it with all the types / template parameters known the template will be used beforehand like this (put it in the .cpp file):
If you don’t know with which template parameters the template will be used, you have to put all the definitions into the header. like
The reason is that when you are going to use the template from somewhere, the compiler has to be able to generate the code for that specific instantiation of the template. But if you place the code into a .cpp file and compile it, there is no way for the compiler to get its hands on the code to generate the instantiation (except when using the infamous
exportkeyword, which is only supported by very few compilers).This is also an entry in my C++ Pitfalls answer: What C++ pitfalls should I avoid?