3

I am trying to implement a leftist tree using heaps as a base class. The following is the contents of heap.h:

template <class T>

class heap {
public:
    virtual void init(T*) = 0;
    virtual void insert(T*) = 0;
    virtual T delete_min() = 0;
};

The following is the contents of leftist.cpp:

#include "heap.h"

template <class T>
class leftist_tree : public heap<T> {
private:
    T* root;
public:
    void init(T* a) {}
    void insert(T* a) {}
    T delete_min() {T a; return a;}
};

I am passing another class leftist_node as a parameter to this class using the following definition:

leftist_tree<leftist_node> mytree;

I am getting an LNK 2001 unresolved external symbol error for functions init, insert and delete_min. What am I doing wrong?

Edit:

Okay the example I have given at this point is far too complex. I have tried to reproduce the same error on a smaller scale so that someone can identify the problem more easily. I have created the following sample files.

try.cpp

#include "stdafx.h"
#include "myclass.h"

int _tmain(int argc, _TCHAR* argv[])
{
    myclass<int> a;
    a.hello(3);
    return 0;
}

myclass.h

template <class T>

class myclass {
public:
    void hello(T);
};

myclass.cpp

#include "myclass.h"
#include <iostream>
using namespace std;

template <class T>
void myclass<T>::hello(T a){
    cout<<a<<endl;
    system("pause");
}

I get a similar error message:

1>try.obj : error LNK2001: unresolved external symbol "public: void __thiscall myclass::hello(int)" (?hello@?$myclass@H@@QAEXH@Z) 1>c:\users\meher anand\documents\visual studio 2010\Projects\try\Debug\try.exe : fatal error LNK1120: 1 unresolved externals

Can you tell me where I am going wrong right now? Thanks

5
  • None of the solutions worked. Surprisingly, when I do not inherit from heap<T> (just declare it as class leftist_tree { ... }) I don't get any compilation errors. Commented Oct 2, 2010 at 1:14
  • I can't seem to reproduce the error. what is leftist_node? is your third code block, the definition for mytree, in the same compilation unit corresponding to leftist.cpp? Commented Oct 2, 2010 at 1:21
  • Always put template code in header files. In this case, what you show in leftist.cpp should be in leftist.h. Also, your declaration of leftist_tree throws away the virtual for its heap methods, so make sure you don't attempt to "override" these methods in a subclass of leftist or things will get weird. Commented Oct 2, 2010 at 2:36
  • @Mike, I thought the rule was once virtual, always virtual? That is, overridden functions will be virtual even if you don't declare them as such. Am I wrong, or are template functions different? Commented Oct 2, 2010 at 14:56
  • @Mark: I just tried it and it looks like that is the case. I stand corrected. Commented Oct 3, 2010 at 14:46

4 Answers 4

3

Template functions are treated a little differently from regular functions. The compiler doesn't actually compile the function until you try to use it. If the only place you try to use it is a .cpp where the body of the function is undefined, it assumes it must be compiled somewhere else and makes a reference for the linker to fill in later.

In your case you defined the body of the functions in leftist.cpp, but you didn't use it there, you used it somewhere else. If you had defined it in the .h file then the definition would have been available everywhere you tried to use it and all would be well. If you had used the functions somewhere in leftist.cpp then the functions would have been created and the linker would have fixed everything up.

The general rule is to define the body of all template functions in the header files.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for that. Learnt something new today. :)
3

The template isn't instantiated for the type. The easiest way is to remove the .cpp from being compiled, and include it into the cpp where you use the template.

Another easy answer is to just define the whole template in the .h.

Comments

1

Whenever you see this error

error LNK20XX unresolved external symbol

It means that while linking the linker is unable to find the function definition. In your case it is error

Hope this helps you. Let me know if you need any more help

PK

1 Comment

That's right up until the main function part. They either have a main or it's a library. The error specifically is listing the functions it can't find.
1

The following should work (tested with g++):

// File: heap.hh --------------------------
template <class T>
class heap {
public:a
    virtual void init(T*) = 0;
    virtual void insert(T*) = 0;
    virtual T delete_min() = 0;
};

// File: leftist_tree.hh ------------------
#include "heap.hh"
template <class T>
class leftist_tree : public heap<T> {
private:
    T* root;
public:
    void init(T* ) {}
    void insert(T* ) {}
    T delete_min() {T a; return a;}
};

// File: leftist_node.hh ------------------
struct leftist_node {
    int value;
};

// File: leftist_main.cpp -----------------
#include "leftist_tree.hh"
#include "leftist_node.hh"

int main() {
    leftist_tree< leftist_node > mytree;
}

2 Comments

Might want to make leftist_node a struct so you can get to its member.
@Mike DeSimone: Good suggestion, thanks for mentioning that. Edited to make that change.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.