2009-12-05 13 views
8

ho una classe template basato [Allotter.h & Allotter.cpp]:errore del linker 'simbolo esterno non risolto': lavorare con i modelli

template <typename allotType> class Allotter { 
public: 
Allotter(); 
quint32 getAllotment(allotType*); 
bool removeAllotment(quint32, int auto_destruct = 0); 

private: 
QVector<QPair<quint32, allotType*>> indexReg; 
int init_topIndex; 
}; 

ed è l'utilizzo è indicato come [ActiveListener.h & ActiveListener. cpp]:

class ActiveListener: public QObject { 
Q_OBJECT 

public: 
ActiveListener(); 

private slots: 
    void processConnections(); 
    void readFromSocket(int); 

private: 
QTcpServer* rootServer; 
QSignalMapper* signalGate; 
Allotter<QTcpSocket> TcpAllotter; 
}; 

Non sto mostrando le definizioni complete, poiché non ha molta importanza. Il problema è quando compilo, tutti i file vengono compilati correttamente. I file si trovano in un progetto VC++. In precedenza, quando non usavo un approccio basato su modelli per Allotter, tutto era compilato e collegato bene. Ma ora, ottengo questo errore:

1>ActiveListener.obj : error LNK2019: unresolved external symbol "public: __thiscall Allotter<class QTcpSocket>::Allotter<class QTcpSocket>(void)" ([email protected]@@@@[email protected]) referenced in function "public: __thiscall ActiveListener::ActiveListener(void)" ([email protected]@[email protected]) 
1>ActiveListener.obj : error LNK2019: unresolved external symbol "public: unsigned int __thiscall Allotter<class QTcpSocket>::getAllotment(class QTcpSocket *)" ([email protected][email protected]@@@@[email protected]@@Z) referenced in function "private: void __thiscall ActiveListener::processConnections(void)" ([email protected]@@AAEXXZ) 

La cosa sorprendente è che il costruttore, ActiveListener::ActiveListener() non fa alcun riferimento a tutti Allotter<QTcpSocket>::Allotter(). Il secondo riferimento tuttavia esiste. Ma non capisco perché il linker non sia in grado di risolvere questo simbolo esterno.

L'uscita costruire poco prima della comparsa degli errori è:

1>Moc'ing ActiveListener.h... 
1>Compiling... 
1>stdafx.cpp 
1>Compiling... 
1>ActiveListener.cpp 
1>Allotter.cpp 
1>moc_ActiveListener.cpp 
1>main.cpp 
1>Generating Code... 
1>Linking... 

Non capisco se niente di tutto questo è rilevante, soprattutto perché tutto questo usato per funzionare perfettamente prima. È solo che dopo aver usato i modelli è stato causato un problema. Qualsiasi aiuto sarà apprezzato. Molte grazie.

+0

Grazie a tutti per la quantità di aiuto che ci hai fornito. Ho fatto un po 'di ricerca la mia auto e hanno trovato un po' una soluzione per lo stesso problema: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 sto mettendo qui per gli altri che capita di inciampare qui alla ricerca di soluzioni a problemi simili. Grazie ancora: D –

+0

possibile duplicato dell'errore di collegamento ["Simboli non definiti" con semplice classe modello] (http://stackoverflow.com/questions/999358/undefined-symbols-linker-error-with-simple-template-class) –

risposta

16

Non è possibile dividere i modelli in file .he cpp - è necessario mettere il codice completo per il modello nella file h.

+5

A meno che non si usi 'export', che funziona solo nelle fiabe. –

+0

@Charles: 'export' funziona nella vita reale (con il compilatore Comeau). –

+0

grazie mille per questo: D Potresti solo illuminarmi sul motivo per cui ciò accade? Presumo che ogni volta che il compilatore richiede una classe specifica da un modello, ad esempio MyClass da MyClass

1

Poiché non è possibile inserire l'implementazione del modello nei file .cpp, è consigliabile utilizzare i file .inl per l'implementazione del modello e includerli dalle intestazioni del modello.

4

In generale si ritiene le migliori pratiche di scrivere il codice del modello del tutto i file di intestazione all'interno. C'è una ragione tecnica importante per questo: quando istanziate un modello, il compilatore C++ ha bisogno di generare codice da quel modello che è specifico per i parametri del modello che avete specificato. Se il codice del modello è inserito interamente nelle intestazioni, ciò viene fatto automaticamente.

E 'è sicuramente possibile scrivere il codice del modello nel modo in cui si ha, con l'implementazione posta nei file cpp. In tal caso, tuttavia, è necessario creare un'istanza esplicita dell'istanza del modello che si intende utilizzare.

Nel tuo caso, è necessario aggiungere la seguente riga in un file cpp nel progetto:

template class Allotter<QTcpSocket>; 
Problemi correlati