C ++ binding errors: Undefined characters using class template

I get some really terrible communication errors from the class I wrote. I completely cannot find anything that will describe what is happening.

Visual Studio (Windows XP)

players.obj: error LNK2019: unresolved external character "public: __thiscall TreeNode :: TreeNode (void)" (? 0? $ TreeNode @VPlayer @@@@ QAE @XZ) referenced by the function "public: __thiscall PlayerList :: PlayerList (void) "(? 0PlayerList @@ QAE @XZ)

Xcode (OSX 10.5)

Undefined characters: "TreeNode :: ~ TreeNode ()" referenced by: 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(){} 
+6
c ++ linker
source share
4 answers

When you define your template in a .cpp file, you need to explicitly create an instance of it with all the type / template parameters known as the template will be used in advance (put it in the .cpp file):

 template class TreeNode<Player>; 

If you do not know with what template parameters the template will be used, you should put all the definitions in the header. as

 template<typename T> class TreeNode { public: TreeNode() /* now, also put the code into here: */ { doSomething(); } }; 

The reason is that when you are going to use the template somewhere, the compiler should be able to generate code for this particular copy of the template. But if you put the code in a .cpp file and compile it, the compiler will not be able to process the code to create the instance (unless you use the notorious export keyword, which only supports a few compilers).

This is also a post in my answer to C ++ Pitfalls: What C ++ pitfalls should be avoided?

+14
source share

Well you declare ~ TreeNode (), but do you define it?

When you declare a destructor, you stop the compiler from creating it, but you must define it somewhere, even if it is empty.

If your intention was to have an empty destructor, you have two options:

-Remove the declaration of ~ TreeNode () completely and rely on a self-generated destructor -Define this as empty. Inlin would be very good here, IE. ~ TreeNode () {};

+2
source share

The compiler complains that it did not find a destructor implementation. As stated above, if you declare a destructor, the compiler will not automatically generate it for you.

To David Reis's suggestion of removing or providing an empty destructor, I would obviously go for the second. If your class needs to be inferred (you have virtual methods), you must provide a virtual destructor even if it is empty (the same applies to BaseNode).

If you depend on the generated version of the compiler and user code, it deletes the derived object using a pointer to a base class whose constructor is not virtual, then the destructor of the derived object will not be called, possibly a resource leak.

+1
source share

Do you forget to link the object file containing the function bodies to your class functions?

eg. you have something like this in .cpp:

 TreeNode::TreeNode() : /* initializers here */ { // ... } TreeNode::~TreeNode() { // ... } 
0
source share

All Articles