2012-01-12 34 views
14

Duplicar posible:
Why can templates only be implemented in the header file?Incluye el archivo .cpp?

he estado tratando un poco con C++ recientemente. Por el momento estoy tratando de programar algo que estoy seguro que todos han hecho al menos una vez: una clase LinkedList simple. El código está hecho, pero de alguna manera no puedo compilarlo. He estado buscando en Google y parece que estoy vinculando los archivos del objeto incorrectamente. Eso es lo que mi código básicamente se parece a:

test.cpp

#include "linkedlist.h" 

int main() 
{ 
    LinkedList<int> list; 
    // do something 
} 

linkedlist.h

template <typename T> 
class LinkedList 
{ 
    // a lot of function and variable definitions 
} 

Luego hay un archivo .cpp denominado linkedlist.cpp que contiene todo el código real de la Clase LinkerList Cuando intente compilar test.cpp con el siguiente comando:

g++ ..\src\test.cpp 

Me estoy dijeron que hay una referencia indefinida a ':: LinkedList LinkedList()'. Así que he estado pensando que está siendo vinculado mal ya que hay más de un archivo .cpp, así que lo probamos así:

g++ -c -Wall -O2 ..\src\test.cpp 
g++ -c -Wall -O2 ..\src\linkedlist.cpp 
g++ -s test.o linkedlist.o 

Sin embargo, esto no cambia nada. Los mensajes de error permanecen igual. He estado tratando de encontrar información en internet, sin embargo, realmente no funcionó.

+3

Bien hecho para formular esto de manera completa y coherente. :) Rara vez para un principiante, hoy en día :( –

+0

Dado que 'LinkedList' es una clase de plantilla, los usuarios de esa clase necesitan la definición completa de todos los métodos. Una forma de hacerlo es tener todos los métodos en línea en la clase, mientras que otra es para poner los métodos en un archivo separado e incluirlos en el archivo de encabezado. –

+0

@Mike: Es difícil llamar a eso un "duplicado" per se. Aquí es donde las cosas se ponen borrosas: la pregunta es completamente diferente, aunque no nos pongamos no es necesario cubrir el mismo terreno otra vez :) :) –

Respuesta

5

Está creando una plantilla de clase, que tiene la importante advertencia de que todas las definiciones de variables deben colocarse en el archivo de encabezado para que sean accesibles para todas las unidades de traducción durante la compilación.

La razón es la forma en que funcionan las plantillas. Durante la compilación, el compilador crea instancias de clases de plantilla en función de la definición de plantilla de su clase. No es suficiente que tenga acceso solo a las declaraciones o firmas: necesita tener toda la definición disponible.

Mueva todas las definiciones de sus métodos fuera del archivo .cpp y en el archivo .h, y todo debería estar bien (¡suponiendo que de hecho haya proporcionado una definición para el constructor predeterminado!).

Alternativamente, puede ser capaz de evitar esto diciendo explícitamente a su compilador que cree una instancia de la clase de plantilla adecuada utilizando algo como template class LinkedList<int>, pero esto realmente no es necesario en un caso tan simple. La principal ventaja de esto sobre la inclusión de todas las definiciones en el archivo de encabezado es que potencialmente reduce la saturación del código y acelera la compilación. Pero puede que no sea necesario en absoluto, ya que los compiladores se han vuelto mucho más inteligentes al aplicar las optimizaciones adecuadas.

+2

La palabra clave 'export' ya no existe, y antes solo era vagamente admitida. –

2

Has dividido tu clase LinkedList y has puesto la declaración en un encabezado y la definición en un archivo fuente. This does not work for a template. Ambos deben estar en el encabezado.

+0

Dijo de hecho 'Luego hay un archivo .cpp llamado linklist.cpp que contiene todo el código real de la clase LinkerList. –

+0

Eso es lo que obtengo solo por las preguntas de desnatado - lo arreglé. –

+0

Le han perdonado preguntas como esta;) –

1

Dado que LinkedList es una clase plantilla, the definitions of its member functions ought to go in a header.

(Ellos no tienen ser, estrictamente hablando, pero esta es la forma más fácil de moverse por las complejidades de instancias de plantilla sin ir totalmente fuera de pista con los convenios de inclusión.)

Ah, y necesitaría tomar su segundo enfoque de construcción de todos modos; debe vincular todos los archivos .cpp, o usar el interruptor -c para compilar uno a la vez y luego vincular los resultados más adelante.

0

hay una referencia indefinida a ':: LinkedList LinkedList()'

¿Ha comprobado para ver si la clase LinkedList tiene un constructor?

1

La clase de plantilla es como una definición de una regla para construir una clase real. Las clases reales son creadas (instanciadas) por el compilador donde haya instanciación de clase de plantilla. Por esta razón, todo el código de la clase de plantilla debe ser visible para un compilador en ese punto, y es por eso que debe escribir todas las funciones y métodos de plantilla en un archivo de encabezado, porque solo incluye encabezados para los archivos cpp, solo los encabezados son visibles a un compilador en ese punto. No incluye archivos cpp en otros archivos cpp, y nunca debería hacer eso.

Corrígeme si mi entendimiento es incorrecto.

P. S. ¿C++ 11 soluciona este problema?

+1

P.S. No. No, no es así. C++ 03 intentó y falló, por lo que C++ 11 se dio por vencido y en realidad eliminó el intento. –

Cuestiones relacionadas