0

For few days I'm trying to compile one project written in C++ using Code::Blocks IDE (on Linux, Ubuntu 64-bit). Code is valid but there are some linker errors. I noticed that I get errors 'undefined reference' for functions which are not inline defined in classes and are in other files (class is i *.h file and definitions on these functions are in *.cpp). I tried to write my own Makefile but it didn't help.

Makefile:

all: project

project: main.o DList.o Person.o
    g++ main.o DList.o Person.o -o project

main.o: main.cpp
    g++ -c main.cpp

DList.o: include/DList.cpp
    g++ -c include/DList.cpp

Person.o: include/Person.cpp
    g++ -c include/Person.cpp

clean:
    rm -rf *.o

I don't know what should I do although I read some about these errors on the net.

// EDIT I changed Object.cpp and Object.h to Person.cpp and Person.h, moved *.cpp files to main directory and changed #include paths in *.cpp files.

Errors:

obj/Debug/main.o||In function `main':|
...main.cpp|19|undefined reference to `DListIterator<Person>::go(int)'|
...main.cpp|20|undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <Person>(std::basic_ostream<char, std::char_traits<char> >&, DList<Person>&)'|
...main.cpp|21|undefined reference to `DList<Person>::~DList()'|
...main.cpp|21|undefined reference to `DList<Person>::~DList()'|
obj/Debug/main.o||In function `DList<Person>::insert(Person&)':|
...include/DList.h|45|undefined reference to `DList<Person>::insert(Person&, DListIterator<Person>&)'|
||=== Build finished: 5 errors, 0 warnings ===|

It makes no difference if I build starting make in command line or using Build function in Code::Blocks.

When I copied all code from *.cpp files to *.h files, compiler returned no errors, so I think that it's only linker problem.

6
  • I think it's a linker order issue. Try DList.o Object.o main.o. Commented Aug 28, 2012 at 7:06
  • I've tried different cases. In every order there are the same errors. Commented Aug 28, 2012 at 7:09
  • 2
    Can you post the exact linker error and also in what fashion that function is contained by .h and .cpp files Commented Aug 28, 2012 at 7:10
  • 100% confirm that the specific things you are being told are undefined are in fact in one of the .cpp files corresponding to one of the .o files you are linking. Commented Aug 28, 2012 at 7:10
  • 1
    Why are your source files in your include directory? Commented Aug 28, 2012 at 7:16

1 Answer 1

4

It looks like you are attempting to separately compile a template. This is not possible in general, as a template will only be instantiated when it is used, and it is never used in the DList.cpp file. Try one of two things:

  • Move the definitions of the functions in DList into the header file (this is the normal way of doing things).
  • Put some explicit instantiations of DList in to the DList.cpp file. (Example: template class DList<Person>;)

Full example of the problem: Currently you have:

//DList.h
template<typename T>
class DList {
    void insert(T& newPerson);
    //etc
};

//DList.cpp
#include "DList.h"
//The when this is being compiled, 
//the compiler does not know about Person,
//so it cannot instantiate this function.
template<typename T>
void DList<T>::insert(T& newPerson) {
    //implementation
}
//etc

//main.cpp
#include "DList.h"
#include "Person.h"
int main() {
    //When this is being compiled, it does not know the
    //definition of the out-of-line functions in `DList`,
    //so it cannot instantiate them.
    DList<Person> people;
    people.insert(Person("Joe"));
}

One possible fix is to remove DList.cpp and put the definitions in "DList.hpp":

//DList.hpp
template<typename T>
class DList {
    void insert(T& newPerson) {
        //implementation
    }
    ~DList();
    //etc
};
//the implementations can alternatively be
//placed outside the class, but in the header:
template<typename T>
DList<T>::~DList() {
    //implementation
}

The other fix is to explicitly instantiate DList (in a compilation unit where the definitions are available):

//DList.cpp
#include "DList.h"
#include "Person.h"
template<typename T>
void DList<T>::insert(T& newPerson) {
    //implementation
}
//Explicit instantiation:
template class DList<Person>;
Sign up to request clarification or add additional context in comments.

2 Comments

First of your suggestions helped. The second not, but it's ok. Is any case in which I can put definitions of template's methods into other file (.cpp)?
Thanks! It seems I had asleeped while was learing about this :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.