Avatar billede driis Nybegynder
14. april 2003 - 14:55 Der er 9 kommentarer og
1 løsning

Templates problem / "Unresolved external symbol"

Jeg sidder og er i gang med at lave en kø-klasse, som via templates gerne skulle understøtte forskellige datatyper. Jeg kan udmærket compile klassen, men når jeg forsøger at anvende den i et testprogram får jeg fejlen "Unresolved external symbol:", hver gang der laves et kald til klassen. Nu er jeg ikke så meget inde i templates, og jeg kan ikke se, hvad der er galt. Herunder er headeren til klassen:

template< class T >
class RingFIFO
{                                    // Overload af stream insertion operator.
    friend ostream &operator<< (ostream &out, const RingFIFO &ob) ;
public:
    RingFIFO(int size = 10) ;            RingFIFO(const RingFIFO &ob);  // Copy constructor
    ~RingFIFO() ;                   
    RingFIFO &operator=(const RingFIFO &ob) ;
    bool putData(T value) ;       
        T    getData() ;   
        bool isFull() ;   
    bool isEmpty();
    int  count() ;                private:
    int size ;
    T  *data;
    int front ;
    int back  ;
};

Herunder nøjes jeg med at indsætte koden til constructor og destructor for ikke at gøre spørgsmålet for langt:
#include "RingFIFO.h"

// Constructor
template<class T>
RingFIFO<T>::RingFIFO(int qSize)
{
    size = qSize ;
    data = new T [size] ;
    for ( int i = 0 ; i < size ; i++ )
        *(data+i) = 0 ;
    front = 0 ;
    back =  0 ;
}


// Destructor
template<class T>
RingFIFO<T>::~RingFIFO()
{
    delete [] data ;
}

Endelig forsøger jeg at benytte klassen i et test program. Her går det galt:
#include "RingFIFO.h"
int main()
{
    RingFIFO<int> iQ ;
    RingFIFO<double> dQ(2) ;
        return 0 ;
}

Hvad kan der være galt ?
Avatar billede soreno Praktikant
14. april 2003 - 15:26 #1
Du skal lave hele implementationen i én fil. F.eks. .h filen.
Avatar billede arne_v Ekspert
14. april 2003 - 15:39 #2
Skulle det gøre nogen forskel ?

(normalt vil pre-processoren jo include .h filen inden selve
compileringen)
Avatar billede driis Nybegynder
14. april 2003 - 15:41 #3
Ja, hvorfor skal hele implementationen ligge i én fil ? Men jeg prøver lige.
Avatar billede driis Nybegynder
14. april 2003 - 15:53 #4
Det virker når det ligger i en fil. Nu vil jeg meget gerne have forklaret, hvorfor ? Og er der ikke en måde at undgå, at det hele kommer til at ligge i en fil ?
Avatar billede soreno Praktikant
14. april 2003 - 16:28 #5
Jeg må indrømme at jeg ikke kan komme med en fornuftig forklaring.
Avatar billede olennert Nybegynder
14. april 2003 - 16:30 #6
Forklaringen er, at din objektkode ikke kan instantieres før oversætteren ved hvilken template parameter du bruger (altså, om du har gang i en RingFIFO<int>, en RingFIFO<double>, eller en RingFIFO<SvendBent>, hvor SvendBent er en af dine egne klasser). Så definitionen af RingFIFO i .h filen er ikke nok til at lave objektkoden til RingFIFO<int> eller nogen af de andre, .cc filen skal med.

Pointen er, at du kan bruge hvad som helst som template-parameter. Og oversætteren generer en gang objektkode til RingFIFO<int>, en ny gang objektkode til RingFIFO<double> og så videre. Det betyder også at du ved brug af templates risikerer en eksplosion i størrelsen af din objektkode. Der er et par fif man kan bruge i den forbindelse.

Det mest klassiske fif er partiel specialisering for pointere. Du laver en fuld specialisering for void*, og så laver du en partiel specialisering til T*, som bruger void* specialiseringen, men cast'er pænt.
Avatar billede driis Nybegynder
14. april 2003 - 16:44 #7
olennert >> Mange tak for den fine forklaring.
Avatar billede arne_v Ekspert
14. april 2003 - 16:45 #8
OK.

Så det er ligegyldigt om erklæringen er i en seperat fil eller ej.

Men implementation skal være i den samme fil der bruger den.

?
Avatar billede olennert Nybegynder
14. april 2003 - 16:58 #9
driis> Velbekomme.

Arne> Ja, du skal have både definition (normalt i .h filen) og erklæring (normalt i .cc filen) ind hvor du skal instantiere. Normalt er det nok med .h filen, men med templates skal erklæringen også med (indtil oversætter teknologien bliver smart nok til at understøtte import keyword'et fra ANSI C++).

Hvis du (som jeg) foretrækker stadig at have definition og erklæring hver for sig, så kan du lade din .h fil slutte med #include "filnavn.cc".
Avatar billede segmose Nybegynder
15. april 2003 - 10:28 #10
olennert> Det er ganske rigtigt en god måde at få meget store exe filer på medmindre at jeg fejlagtigt erindre at Bjarne har lovet mig at der kun skulle komme en function for hver template instatirering, så selvom du tager det hele med i hver objectfil skulle det endelige program eliminere duplikerede instatierede functioner.

Skulle dette ikke være tilfældet (som i min ikke helt standard compiler) kan man snyde lidt og gøre compilerens arbejde for den, bruge .h i alle object filer og lave en særlig instance fil, hvor du instantierer alle de templates du bruger i programmet og for dermed oprettet alle de nødvendige functioner og hermed fjernet linker fejlen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester