los_templates_me_odian_no_tienen_piedad

transistor47
21 de Abril del 2006
Hola a todos, y es que los templates me odian no tienen piedad conmigo :(.

Estoy haciendo un programa de lo más tonto y me salen errores solamente cuando hago el linkado:

unresolved external symbol "public: class cComplejo<int> __thiscall cComplejo<int>::operator+(class cComplejo<int>)" ([email protected]@@[email protected]@@Z)

unresolved external symbol "class ostream & __cdecl operator<<(class ostream &,class cComplejo<int> &)" ([email protected]@@[email protected][email protected]@@@Z)

error LNK2001: unresolved external symbol "public: __thiscall cComplejo<int>::cComplejo<int>(int,int)" ([email protected]@@[email protected]@Z)

El código es muy sencillo y no sé por qué no encuentra las funciones al hacer el linkado:

*****************************clase_complejo.h*****************************
#ifndef __CLASE_COMPLEJO_H__
#define __CLASE_COMPLEJO_H__
#include <iostream.h>
//El mismo concepto de plantillas de funciones se pueden aplicar a las clases
template <class Tipo>
class cComplejo
{
private:
Tipo real;
Tipo imaginaria;
public:
cComplejo(Tipo, Tipo);
cComplejo operator+(cComplejo);
friend ostream& operator <<(ostream &salida,cComplejo &complejo);
};
#endif
***********************clase_complejo.cpp*********************************
#include <iostream.h>
#include "clase_complejo.h"

template <class Tipo>
cComplejo<Tipo>::cComplejo<Tipo>(Tipo real, Tipo imaginaria){
this->real = real;
this->imaginaria = imaginaria;
};

template <class Tipo>
cComplejo<Tipo> cComplejo<Tipo>::operator+(cComplejo<Tipo> operando2){
this->real = this->real + operando2.real;
this->imaginaria = this->imaginaria + operando2.imaginaria;
};

template <class Tipo>
ostream& operator <<(ostream& salida,cComplejo<Tipo> &complejo){
salida << "Real: " << complejo.real << endl;
salida << "Imaginaria: " << complejo.imaginaria << endl;
return salida;
};

*********************************************************ppal.cpp*********************

#include <iostream.h>
#include "clase_complejo.h"

void main(){
//Se le indica el tipo de dato que va a manipular la clase
cComplejo <int> complejo1(1, -3);
cComplejo <int> complejo2(2, 1);
cComplejo <int> complejo3(0, 0);

cout << "Complejo 1: " << endl << complejo1;
cout << "Complejo 2: " << endl << complejo2;

complejo3 = complejo1 + complejo2;
cout << "Complejo 3: " << endl << complejo1;
}

Muchas gracias a todos.

Un saludo,

Daniel

hiei
21 de Abril del 2006
Siiiiii!!!!!!... Ya somos dooooossss!!!!!
Bueno, lo primero, es que (y esto no te lo dice nadia ni esta en ninguna parte) saber que el asunto de los templates es una especie de declaracion en tiempo de compilacion (en enlazador no tiene nada que ver... es una artimaña del compilador que hace que auto-escriba codigo partiendo de una base... pero el codigo se repite para cada tipo de datos...)
Asi que lo que tienes que hacer es poner las funciones de clase_complejo.cpp en el archivo de cabezera... no te preocupes porque cuando se genere el codigo este no interferira entre distintos ficheros objetos porque solo lo ve el compilador no el linker... De todas formas, si no te gusta mucho esa solucion haz una clase generica con punteros a VOID que implemente el algoritmo basico y luego haz derivados de esa clase como templates que implementen la interfaz haciendo el casting adeguado...

Bueno, aclaracion al marjen... los templates no me gustan... porque tambien me odian a mi...