2010-09-14 18 views
14

[[UPDATE]] -> Si #incluyo "Queue.cpp" en mi programa.cpp, funciona bien. Esto no debería ser necesario, ¿verdad?C++ - LNK2019 error símbolo externo sin resolver [constructor y destructor de la clase de plantilla] al que se hace referencia en la función _main

Hola a todos: estoy usando Visual Studio 2010 y tengo problemas para vincular una implementación de cola rápida y sucia. Comencé con una aplicación de consola vacía Win12, y todos los archivos están presentes en el proyecto. Para verbosidad, aquí está el código completo para duplicar mi error. Me doy cuenta de que parte del código puede, de hecho, estar equivocado. No he tenido la oportunidad de probarlo todavía porque aún no he podido vincularlo.

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; 
} 

Y los errores ...

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

Así como notas generales sobre el código; no es necesario incluir guardias para cada clase en un encabezado, y hacerlo es mucho más probable que entren en conflicto. En su lugar, coloque un protector de inclusión alrededor del encabezado completo, basado en el nombre de archivo de ese encabezado. Es una práctica estándar y es menos probable que se encuentre con otros nombres de archivos. –

+0

Duplicado de [Error de enlazador LNK2019] (http://stackoverflow.com/questions/3680312/linker-error-lnk2019) (Esta pregunta se realiza aproximadamente cinco veces por semana) –

Respuesta

13

¿Por qué no sigues el "Inclusion Model"? Te recomendaría que sigas ese modelo. El compilador necesita tener acceso a toda la definición de la plantilla (no solo a la firma) para generar código para cada instanciación de la plantilla, por lo que debe mover las definiciones de las funciones a su encabezado.

Nota: En general, la mayoría de los compiladores de C++ no admiten fácilmente el modelo de compilación separado para las plantillas.

Por otra parte es necesario para leer this.

4

Los errores del vinculador se deben a que ve los archivos de encabezado de Queue.hpp, pero no ve las definiciones de las funciones. Esto se debe a que es una clase de plantilla, y para C++, las definiciones de las plantillas deben estar en el archivo de encabezado (hay algunas otras opciones, pero esa es la solución más fácil). Mueva las definiciones de las funciones de Queue.cpp a Queue.hpp y compile.

+0

Sí, todos los archivos están incluidos. Si, por ejemplo, omito un punto y coma en Queue.cpp, el proyecto no llega al proceso de vinculación porque de repente no se puede compilar. – Squirrelsama

+0

No me di cuenta de que era una plantilla durante mi primer pase; eso explica el error. –

+0

¿Por qué las plantillas causan este error? Además ... [[UPDATE]] -> Si incluyo "Queue.cpp" en mi programa.cpp, funciona bien. Esto no debería ser necesario, ¿verdad? – Squirrelsama

4

Se debe tener acceso a todos los códigos de plantilla durante la compilación. Mueva los detalles de implementación de Queue.cpp al encabezado para que estén disponibles.

4

Si usted tiene:

template <typename T> 
void foo(); 

Y que hacer:

foo<int>(); 

El compilador necesita generar (instantiate) esa función. Pero no puede hacerlo a menos que la definición de la función sea visible en el momento de la instanciación.

Esto significa que las definiciones de las plantillas se deben incluir, de alguna manera, en el encabezado. (Puede incluir la .cpp al final de la cabecera, o simplemente proporcionar las definiciones en línea.)

2

Un ejemplo para resolver el error LNK2019:
Se tiene que escribir # include "EXAMPLE.cpp" al final de .h archivo

//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 
//---------------------------------------------- 

En el archivo .cpp hacer lo siguiente

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

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

#endif 
//----------------------------------------------- 
Cuestiones relacionadas