View Full Version : [C++]Problema con template
Kleidemos
30-03-2003, 09:24
Mi sono creato una class Vettore che implementa i seguneti metodi:
///////////////////////////////
// Costruttori/distruttori
///////////////////////////////
Vettore();
Vettore(int dim);
virtual ~Vettore();
///////////////////////////////
// Utilita di ricerca
///////////////////////////////
void Ordina();
int cerca(T key);
///////////////////////////////
// Funzioni di interfaccia
///////////////////////////////
int getDimensione();
T getElemento(int pos);
///////////////////////////////
// Funzioni vettore
///////////////////////////////
void AggiungiElemento(T elemento, int pos);
void AggiungiElemento(T elemento);
void RimuoviElemento(int pos);
Pero quando cerco di linkarlo mi da questi errori:
--------------------Configuration: Vettore - Win32 Debug--------------------
Linking...
Test.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall Vettore<int>::~Vettore<int>(void)" (??1?$Vettore@H@@UAE@XZ)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::cerca(int)" (?cerca@?$Vettore@H@@QAEHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::getElemento(int)" (?getElemento@?$Vettore@H@@QAEHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::getDimensione(void)" (?getDimensione@?$Vettore@H@@QAEHXZ)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::Ordina(void)" (?Ordina@?$Vettore@H@@QAEXXZ)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::AggiungiElemento(int)" (?AggiungiElemento@?$Vettore@H@@QAEXH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::AggiungiElemento(int,int)" (?AggiungiElemento@?$Vettore@H@@QAEXHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: __thiscall Vettore<int>::Vettore<int>(int)" (??0?$Vettore@H@@QAE@H@Z)
Debug/Vettore.exe : fatal error LNK1120: 8 unresolved externals
Error executing link.exe.
Vettore.exe - 9 error(s), 0 warning(s)
Vi allego il progetto (Visual C++ 6) cosi magari serve anche a qualcuno
/\/\@®¢Ø
30-03-2003, 09:53
Il problema fondamentale sta nel fatto che il compilatore deve generare il codice opportuno per ogni tipo utilizzato come parametro. Ma quando compili il file Vettore.cpp il compilatore non sa che poi vuoi utilizzarlo con int come parametro e quindi il codice non viene generato.
Per risolvere il problema c'e' piu' di una soluzione, la piu' pratica e' quella di includere il sorgente nell'header invece di fare il contrario (e' quella adottata dalla libreria standard del C++, perlomeno fino all'ultima volta che ho controllato :D ).
In Vettore.h dovresti quindi aggiungere
#ifndef VETTORE_H
#define VETTORE_H
// Per evitare inclusioni multiple, andrebbe fatto con ogni file.h
all'inizio e
#include "Vettore.cpp"
#endif
alla fine
Ovviamente devi togliere la riga #include "Vettore.h" dal file Vettore.cpp
Dimmi se ti funziona
ciao
Marco
Kleidemos
30-03-2003, 10:02
nn va lo stesso e mi da 14 errori
/\/\@®¢Ø
30-03-2003, 10:48
Che errori ti da ? (non ho il compilatore sottomano per aiutarti... )
Kleidemos
30-03-2003, 10:50
mi da sempre questi:
Compiling...
Test.cpp
Linking...
Test.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall Vettore<int>::~Vettore<int>(void)" (??1?$Vettore@H@@UAE@XZ)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::cerca(int)" (?cerca@?$Vettore@H@@QAEHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::getElemento(int)" (?getElemento@?$Vettore@H@@QAEHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::getDimensione(void)" (?getDimensione@?$Vettore@H@@QAEHXZ)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::Ordina(void)" (?Ordina@?$Vettore@H@@QAEXXZ)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::AggiungiElemento(int)" (?AggiungiElemento@?$Vettore@H@@QAEXH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::AggiungiElemento(int,int)" (?AggiungiElemento@?$Vettore@H@@QAEXHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: __thiscall Vettore<int>::Vettore<int>(int)" (??0?$Vettore@H@@QAE@H@Z)
Debug/Vettore.exe : fatal error LNK1120: 8 unresolved externals
Error executing link.exe.
Vettore.exe - 9 error(s), 0 warning(s)
Kleidemos
30-03-2003, 11:34
hai ragione!
Cazzo ekko cosa ho dimeticato!
Pero..............almeno sto migliorando, cionci o mio maestro?
Kleidemos
30-03-2003, 11:37
ora mi da:
--------------------Configuration: Vettore - Win32 Debug--------------------
Compiling...
Vettore.cpp
Linking...
Test.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall Vettore<int>::~Vettore<int>(void)" (??1?$Vettore@H@@UAE@XZ)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::cerca(int)" (?cerca@?$Vettore@H@@QAEHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::getElemento(int)" (?getElemento@?$Vettore@H@@QAEHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: int __thiscall Vettore<int>::getDimensione(void)" (?getDimensione@?$Vettore@H@@QAEHXZ)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::Ordina(void)" (?Ordina@?$Vettore@H@@QAEXXZ)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::AggiungiElemento(int)" (?AggiungiElemento@?$Vettore@H@@QAEXH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: void __thiscall Vettore<int>::AggiungiElemento(int,int)" (?AggiungiElemento@?$Vettore@H@@QAEXHH@Z)
Test.obj : error LNK2001: unresolved external symbol "public: __thiscall Vettore<int>::Vettore<int>(int)" (??0?$Vettore@H@@QAE@H@Z)
Debug/Vettore.exe : fatal error LNK1120: 8 unresolved externals
Error executing link.exe.
Vettore.exe - 9 error(s), 0 warning(s)
Devi implementare le funzioni...altrimenti è ovvio che ti dia questi errori !!!
Kleidemos
30-03-2003, 11:41
Originally posted by "cionci"
Devi implementare le funzioni...altrimenti è ovvio che ti dia questi errori !!!
skarikati il files iniziale!
C'è tutto il progetto ;)
Ho fatto casino...andava bene come avevi fatto te...senza il virtual davanti al distruttore...
Il suggerimento di /\/\@®¢Ø e' giusto.
Probabilmente non hai ricompilato completamente il progetto, dato che hai riportato gli stessi identici errori, oppure hai gli header files precompilati. In tal caso disattiva la funzione e riprova.
Riguardo al viratual sul distruttore e' corretto. E' obbligatorio (a meno di non avere leaks) metterlo quando si vuole permettere di sottoclassare la classe che si sta scrivendo.
Kleidemos
31-03-2003, 06:02
risolto!
Ho incluso il files *.cpp e nn quello .h .
Vi allego la mia soluzione
Guarda...è una cosa davvero strana... Sto avendo anche io questi strani errori...e non capisco il perchè ci siano...
Dovrebbe bastare include il .h...
Il bello è che se si infilano anche errori nel .cpp li ignora completamente...Vettore.cpp non lo compila e nemmeno lo linka...
Bah...mai successa una cosa del genere...
Il bello è che me li da sia con VC++ che con Dev-C++...
Kleidemos
31-03-2003, 13:54
hai provato il mio ultimo rar?
Cmq a me includendo il .cpp nn mi da errore e funzia bene!
include il cpp perche ho scoperto che i template nn sono compilati ma sono costruiti sul momento :eek:
Originally posted by "Kleidemos"
include il cpp perche ho scoperto che i template nn sono compilati ma sono costruiti sul momento :eek:
Le varie versioni delle classi template necessarie al funzionamento sono create al momento della compilazione...quindi anche i template sono compilati...
L'ho provato...ma includere il .cpp non è un modo giusto di operare--- Deve andare anche includendo il solo .h...
Kleidemos
31-03-2003, 14:01
andrebbe con il solo .h se io implementassi i template in esso ;)
Originally posted by "Kleidemos"
andrebbe con il solo .h se io implementassi i template in esso ;)
Non è vero...
Prova a dichiarare qualsiasi classe e ad includere solo la dichiarazione le .h...e vedrai che il .cpp se incluso nel progetto viene compilato e linkato all'eseguibile...
Kleidemos
31-03-2003, 15:11
mi rispondi qui? (http://forum.hwupgrade.it/viewtopic.php?t=425915)
Confermo anche io: il codice delle funzioni / classi template deve essere visibile nel punto dove viene usato. Questo almeno e' vero per molti compilatori attuali (io uso il gcc in ambiente Solaris ed ho lo stesso identico comportamento che avete evidenziato nel thread).
Sembra come se le funzioni / classi template siano delle macro.
In effetti ora che ci penso è vero...
Non può assemblare a parte l'obj e poi linkarlo al main perchè non può conoscere a priori quali classi reali vengono usate nell'intero progetto...
Quindi l'unico modo è calcolarsele al volo includendo anche l'implementazione all'interno del sorgente che ne fa uso...
/\/\@®¢Ø
01-04-2003, 14:59
Originally posted by "dm69"
Sembra come se le funzioni / classi template siano delle macro.
Non e' tanto una questione di macro. Piuttosto in generale il compilatore genera codice diverso per ogni possibile parametro del template. Ovviamente non si puo' generare codice per ogni possibile utilizzo, e quindi lo si fa solo per le classi che servono. Inoltre questo permette vari trucchetti, come quello di utilizzare come parametro classi che non implementano tutti i metodi richiesti (se non vengono utilizzati). Per capire quali sono queste classi pero' il compilatore deve avere sottomano il codice che le utilizza nel momento in cui viene analizzato il codice della classe/funzione template, da qui la necessita' di includere il sorgente negli header. In realta' non e' l'unica soluzione: un modo spartano ad esempio consiste nel tenere a parte l'implementazione, ma specificare in quel file anche tutti i possibili utilizzi (soluzione anche peggiore della precedente secondo me). In teoria lo standard prevede anche un modo di "esportare" i template (tramite una direttiva), pero' e' sempre stato un problema implementarlo e' attualmente pochi compilatori danno questa alternativa (e' ancora un word-in-progress sostanzialmente)
/\/\@®¢Ø
01-04-2003, 15:10
Ho controllato ed in effetti nel g++ la keyword ( ops, non direttiva ) export non e' ancora implementata ( cosi' come nel Visual-C++ che stai usando):
http://gcc.gnu.org/bugs.html
Missing features
We know some things are missing from G++.
The export keyword is not implemented.
Most C++ compilers (G++ included) do not yet implement export, which is necessary for separate compilation of template declarations and definitions. Without export, a template definition must be in scope to be used. The obvious workaround is simply to place all definitions in the header itself. Alternatively, the compilation unit containing template definitions may be included from the header.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.