Problems with c++ function template (Reference not defined for class methods)

Asked

Viewed 362 times

0

Hello! I’m trying to compile the following code:

main:
#include "lista.h"

using namespace std;

int main(){
    no<int> *n; 
    n = new no<int>(4);
    n->setProx(new no<int>(5));
    cout << n->obterValor() << endl;
    return 0;
}```

list. h

#ifndef lista_h
#define lista_h

#include <iostream>

using namespace std;

template<typename type> class no{
private:
    type v;
    no *prox;
public:
    no(type v);
    void setProx(no* prox);
    type obterValor();
    no<type>* obterProx();
};

#endif

cpp list.

#include "lista.h"
template<typename type>
no<type>::no(type v){
    this->v = v;
    this->prox = NULL;
}

template<typename type>
void no<type>::setProx(no<type>* prox){
    this->prox = prox;
}

template<typename type>
type no<type>::obterValor(){
    return this->v;
}

template<typename type>
no<type>* no<type>::obterProx(){
    return this->prox;
}

When I compile, as in Makefile:

all:    lista.o main.o
    g++ -o exe lista.o main.o
lista.o:    lista.cpp   lista.h
    g++ -c lista.cpp
main.o: main.cpp    lista.h
    g++ -c main.cpp
go:
    ./exe
clean:
    rm *.o && rm exe

And then the terminal returns me this:

g++ -c main.cpp
g++ -o exe lista.o main.o
/usr/bin/ld: main.o: na função "main":
main.cpp:(.text+0x25): referência não definida para "no<int>::no(int)"
/usr/bin/ld: main.cpp:(.text+0x44): referência não definida para "no<int>::no(int)"
/usr/bin/ld: main.cpp:(.text+0x54): referência não definida para "no<int>::setProx(no<int>*)"
/usr/bin/ld: main.cpp:(.text+0x60): referência não definida para "no<int>::obterValor()"
collect2: error: ld returned 1 exit status
make: *** [makefile:2: all] Error 1

I do not understand why these indefinite references to functions. The main.cpp and list.cpp files are compiled and generate the '.o' object, but the error is time to create the executable.

1 answer

0

The undefined reference error is a Linker error and means that the compiler knows that the function has been declared but does not know where the implementation is. This happened with your code pq a template is not a defined type but a template to define types in the future. Every time a new template type is declared, the compiler searches for the template to instantiate the new template type. That’s why, for example, no<int> is a different kind of no<float>.

When you compiled the list. o, the compiler was unaware of the existence of the type no<int> (declared in main.cpp) and therefore did not compile the implementation for no<int>. Then when you compiled main. o, the compiler tried to create the type in<int> and found the template statement in the list header. h, but did not find the definition of the methods that are in list.cpp.

The solution is to put the method definition of no in the same list header. h:

#ifndef lista_h                                                                                                         #define lista_h

#include <iostream>

using namespace std;

template<typename type> class no{
private:
    type v;
    no *prox;
public:
    no(type v);
    void setProx(no* prox);
    type obterValor();
    no<type>* obterProx();
};

template<typename type>
no<type>::no(type v){
    this->v = v;
    this->prox = NULL;
}

template<typename type>
void no<type>::setProx(no<type>* prox){
    this->prox = prox;
}

template<typename type>
type no<type>::obterValor(){
    return this->v;
}

template<typename type>
no<type>* no<type>::obterProx(){
    return this->prox;
}

#endif

I know it’s weird, but that’s the standard for setting templates in headers.

Compile list. is unnecessary, so I suggest you change your Makefile as well:

all:
        g++ main.cpp -o exe

go:
        ./exe

clean:
        rm *.o && rm exe

Browser other questions tagged

You are not signed in. Login or sign up in order to post.