2010-09-14 3 views
14

[[UPDATE]] -> Если я #include "Queue.cpp" в моей программе program.cpp, он работает нормально. Это не обязательно, не так ли?Ошибка C++ - LNK2019 ошибка неразрешенного внешнего символа [конструктор и деструктор шаблона класса], на который ссылается функция _main

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

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)" ([email protected]@@[email protected]) 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)" ([email protected]@@[email protected]) referenced in function _main C:\[omitted]\Project2_2\Project2_2\program.obj Project2_2 
+1

Так как общие замечания по коду; вам не нужно включать защитников для каждого класса в заголовок, и это гораздо более вероятно, конфликт. Скорее, поместите один включите охрану вокруг всего заголовка, основываясь на имени файла этого заголовка. Это стандартная практика и гораздо менее вероятная работа с другими именами файлов. –

+0

Дубликат [Linker Error LNK2019] (http://stackoverflow.com/questions/3680312/linker-error-lnk2019) (Этот вопрос задается примерно пять раз в неделю) –

ответ

13

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

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

Кроме того, вы должны прочитать this.

4

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

+0

Да, все файлы включены. Если я, например, опускаю точку с запятой в Queue.cpp, проект не переходит к процессу связывания, потому что он неожиданно не компилируется. – Squirrelsama

+0

Я не заметил, что это был шаблон во время моего первого прохода; что объясняет ошибку. –

+0

Почему шаблоны вызывают эту ошибку? Также ... [[UPDATE]] -> Если я # включил «Queue.cpp» в свой файл program.cpp, он работает нормально. Это не обязательно, не так ли? – Squirrelsama

4

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

4

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

template <typename T> 
void foo(); 

И вы делаете:

foo<int>(); 

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

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

2

пример для решения lnk2019 ошибки:
Он должен написать #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 
//-----------------------------------------------