C ++ - LNK2019 ошибка неразрешенного внешнего символа [конструктор и деструктор класса шаблона], на который ссылается функция _main - PullRequest
14 голосов
/ 14 сентября 2010

[[UPDATE]] -> Если я #include "Queue.cpp" в моем program.cpp, он работает просто отлично.В этом не должно быть необходимости, верно?

Привет всем - я использую Visual Studio 2010 и испытываю проблемы с компоновкой быстрой и грязной реализации очереди.Я начал с пустого Консольного приложения Win32, и все файлы присутствуют в проекте.Для многословия вот полный код, дублирующий мою ошибку.Я понимаю, что часть кода может на самом деле ошибаться.У меня еще не было возможности протестировать его, потому что я еще не смог связать его.

Queue.hpp

#ifndef ERROR_CODE
#define ERROR_CODE
enum Error_Code
{
    Success,
    Underflow,
    Overflow
};
#endif // ERROR_CODE

#ifndef QUEUE
#define QUEUE
template<class T>
struct Queue_Node
{
    T data;
    Queue_Node *next;

    Queue_Node()
    {
        next = NULL;
    }
    Queue_Node(T pData)
    {
        data = pData;
        next = NULL;
    }
    Queue_Node(T pData, Queue_Node *pNext)
    {
        data = pData;
        next = pNext;
    }
};

template<class T>
class Queue
{
public:
    Queue();
    Error_Code Serve();
    Error_Code Append(T item);
    T Front();
    ~Queue();

private:
    void Rescursive_Destroy(Queue_Node<T> *entry);
    Queue_Node<T> *front, *rear;
};
#endif // QUEUE

Queue.cpp

#include "Queue.hpp"

template <class T>
Queue<T>::Queue()
{
    this->front = this->rear = NULL;
}

template<class T>
Error_Code Queue<T>::Serve()
{
    if(front == NULL)
        return Underflow;

    Queue_Node *temp = this->front;
    this->front = this->front->next;
    delete temp;
}

template<class T>
Error_Code Queue<T>::Append(T item)
{
    Queue_Node *temp = new Queue_Node(item);
    if(!temp)
        return Overflow;

    if(this->rear != NULL)
        this->rear->next = temp;
    this->rear = temp;

    return Success;
}

template<class T>
T Queue<T>::Front()
{
    if(this->front == NULL)
        return Underflow;
    return this->front->data;
}

template<class T>
Queue<T>::~Queue()
{
    this->Rescursive_Destroy(this->front);
}

template<class T>
void Queue<T>::Rescursive_Destroy(Queue_Node<T> *entry)
{
    if(entry != NULL)
    {
        this->Recursive_Destroy(entry->next);
        delete entry;
    }
}

program.cpp

#include "Queue.hpp"

int main()
{
    Queue<int> steve;
    return 0;
}

И ошибки ...

Error   1   error LNK2019: unresolved external symbol "public: __thiscall Queue<int>::~Queue<int>(void)" (??1?$Queue@H@@QAE@XZ) referenced in function _main    C:\[omitted]\Project2_2\Project2_2\program.obj  Project2_2
Error   2   error LNK2019: unresolved external symbol "public: __thiscall Queue<int>::Queue<int>(void)" (??0?$Queue@H@@QAE@XZ) referenced in function _main C:\[omitted]\Project2_2\Project2_2\program.obj  Project2_2

Ответы [ 5 ]

14 голосов
/ 14 сентября 2010

Почему бы вам не следовать "Модели включения" ?Я бы порекомендовал вам следовать этой модели.Компилятор должен иметь доступ ко всему определению шаблона (а не только к сигнатуре), чтобы генерировать код для каждого экземпляра шаблона, поэтому вам нужно перенести определения функций в свой заголовок.

Примечание: В большинстве случаев большинство компиляторов C ++ не поддерживают отдельную модель компиляции для шаблонов.

Более того, вам нужно прочитать this.

4 голосов
/ 04 июня 2016

Пример решения ошибки lnk2019:
В конце файла .h необходимо написать #include "EXAMPLE.cpp"

//header file codes
#pragma once
#ifndef EXAMPLE_H
#define EXAMPLE_H

template <class T>
class EXAMPLE
{

//class members
void Fnuction1();

};


//write this
#include "EXAMPLE.cpp"


#endif
//----------------------------------------------

В файле .cpp выполните следующие действия

//precompile header
#include "stdafx.h"
#pragma once
#ifndef _EXAMPLE_CPP_
#define _EXAMPLE_CPP_

template <class T> 
void EXAMPLE<T>::Fnuction1()
{
 //codes
}

#endif
//-----------------------------------------------
4 голосов
/ 14 сентября 2010

Если у вас есть:

template <typename T>
void foo();

И вы делаете:

foo<int>();

Компилятору необходимо сгенерировать (создать экземпляр) эту функцию.Но он не может этого сделать, если определение функции не видно в момент создания экземпляра .

Это означает, что определения шаблона необходимо каким-то образом включить в заголовок.(Вы можете включить .cpp в конце заголовка или просто указать определения в строке.)

4 голосов
/ 14 сентября 2010

Весь код шаблона должен быть доступен во время компиляции. Переместите подробности реализации Queue.cpp в заголовок, чтобы они были доступны.

4 голосов
/ 14 сентября 2010

Ошибки компоновщика связаны с тем, что он видит заголовочные файлы для Queue.hpp, но не видит определения функций.Это потому, что это класс шаблонов, а для C ++ определения шаблонов должны быть в заголовочном файле (есть несколько других вариантов, но это самое простое решение).Переместите определения функций из Queue.cpp в Queue.hpp, и он должен скомпилироваться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...