Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Шаблоны C++ , undefined reference to

#cpp #шаблоны_с++ #stack


stack.cpp

//stack.cpp
#include "stack.h"

template 
Stack::Stack()
{
    top = nullptr;
}

template 
void Stack::push(T arg)
{
    Node* temp = new Node;
    temp->value = arg;
    temp->next = top;
    top = temp;
}

template 
T Stack::pop()
{
    if (top != nullptr)
    {
        T result = top->value;
        Node* temp = top;
        top = top->next;
        delete temp;
        return result;
    } else
        return 0;
}

template 
Stack::~Stack()
{
    while (top != nullptr)
        pop();
}


stack.h

//stack.h
#ifndef PROJECT_STACK_H
#define PROJECT_STACK_H

template 
class Stack
{
private:
    struct Node
    {
        T value;
        Node* next;
    };
    Node* top;
public:
    Stack();
    void push(T arg);
    T pop();
    ~Stack();
};


#endif //PROJECT_STACK_H


//main.cpp примерно следующего содержания:

Stack  s;
s.push('a');


компилирую через g++ так: g++ -std=c++11 main.cpp stack.cpp

Получаю следующие ошибки:

/tmp/ccvtzAEt.o:main.cpp:(.text+0x1b): undefined reference to `Stack::Stack()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x1b): relocation truncated to fit: R_X86_64_PC32
against undefined symbol `Stack::Stack()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x2c): undefined reference to `Stack::push(char)'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x2c): relocation truncated to fit: R_X86_64_PC32
against undefined symbol `Stack::push(char)'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x3d): undefined reference to `Stack::push(char)'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x3d): relocation truncated to fit: R_X86_64_PC32
against undefined symbol `Stack::push(char)'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x49): undefined reference to `Stack::pop()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x49): relocation truncated to fit: R_X86_64_PC32
against undefined symbol `Stack::pop()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x66): undefined reference to `Stack::pop()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x66): relocation truncated to fit: R_X86_64_PC32
against undefined symbol `Stack::pop()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x9b): undefined reference to `Stack::~Stack()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0x9b): relocation truncated to fit: R_X86_64_PC32
against undefined symbol `Stack::~Stack()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0xae): undefined reference to `Stack::~Stack()'
/tmp/ccvtzAEt.o:main.cpp:(.text+0xae): relocation truncated to fit: R_X86_64_PC32
against undefined symbol `Stack::~Stack()'
collect2: ошибка: выполнение ld завершилось с кодом возврата 1


То есть  undefined reference to Stack::Stack() и undefined reference to Stack::push(char)
и undefined reference to Stack::~Stack()

В чем проблема? Заранее огромное спасибо!
    


Ответы

Ответ 1



Ну откуда же при компиляции stack.cpp компилятору знать, что где-то, в совсем другом файле вам понадобится Stack? Не выносите реализацию шаблонов в отдельный файл, оставляйте ее в заголовочном файле.

Ответ 2



Либо не выносите определения шаблонов в отдельный файл (т.е. реализуйте все в заголовочном файле), либо не забывайте включать этот отдельный файл повсеместно, как включаются обычные заголовочные файлы. На практике у обоих подходов есть свои поклонники. Но при этом давать файлу реализации расширение .cpp не принято - это все таки включаемый, а не отдельно компилируемый файл. Скармливать ваш файл реализации непосредственно компилятору (g++ stack.cpp) бесполезно: определения шаблонов не порождают кода, в чем вы сможете убедиться взглянув на сгенерированный из stack.cpp объектный файл - он будет пуст. P.S. Теоретически, вы можете оставить все как есть, но добавить в stack.cpp явные инстанциации вашего шаблона для всех требуемых типов аргументов. Т.е. в вашем случае достаточно добавить в stack.cpp строчку template Stack; и все сразу заработает в оригинальном виде, при компиляции через ваше g++ -std=c++11 main.cpp stack.cpp. Но, как вы сами понимаете, в общем случае это - не жизнеспособный подход, а специальная фича, предназначенная совсем для других целей.

Комментариев нет:

Отправить комментарий