webForumDet fria alternativet

problem med tempalte<class T>

18 svar · 650 visningar · startad av Mc Fetto

Mc FettoMedlem sedan nov. 20022 355 inlägg
#1

Jag försöker göra en deque med <class T> skickar upp lite kod:

.h fil och .cpp fil

 class Bok {
public:
	void getBok();
	void putBok(Bok minBok);
private:
	char bokTitel[31];

};

template<class T>
class Ko  {
public:
	T popFirst();
	void pushFirst(T Objekt);
	T popLast();
	void pushLast(T Objekt);
private:
	deque<T>* minDeque;

};

template<class T>
void Ko<T>::pushFirst(T Objekt) { 
	minDeque.push_front(Objekt);
}

void Bok::getBok() {
	cout<<"Ange Boktitel:";
	cin.get(bokTitel, 31, '\n');
	cin.get(c);
}

main:

Ko<Bok> minKo;

Bok minBok;
minBok.getBok();
minKo.pushFirst(minBok);

Då får jag följande fel när jag efter kompilering ska länka allt:

error LNK2001: unresolved external symbol "public: void __thiscall Ko<class Bok>::pushFirst(class Bok)" (?pushFirst@?$Ko@VBok@@@@QAEXVBok@@@Z)
error LNK2001: unresolved external symbol "public: void __thiscall Bok::getBok(void)" (?getBok@Bok@@QAEXXZ)
Debug/header.exe : fatal error LNK1120: 2 unresolved externals

Jag har inte en susning om vad det är för fel... någon som vet!?

aasahMedlem sedan mars 20034 471 inlägg
#2

Jag misstänker att problemet har att göra med uppdelningen i cpp och h fil. Just för templates funkar inte den vanliga valsen med att ha implementationen i cpp och definitionen i h. Det här har nånting att göra med att eftersom klassen är okänd så kan inte minnesåtgången beräknas på bra sätt utifrån definitionen. Finns två sätt att komma runt:

  1. Lägg all template klass i EN fil. Döp den till .cpp
  2. Dela upp på vanligt sätt mellan h och cpp men inkludera bakvänt. Dvs skriv i h-filen efter definitionerna
    # include "my_template.cpp"

(Jag brukar köra på 1, så länge inte koden är jättelång känns det enklast.)

Mc FettoMedlem sedan nov. 20022 355 inlägg
#3

Mm tack för tipsen, varken det första elelr det andra får jag att fungera.... När jag gör det andra sättet så får jag massor med felmedelanden om kolon etc som det ska vara fel runt!!
Får nog låta det sjunka in en stund!

Tack

aasahMedlem sedan mars 20034 471 inlägg
#4

Ahh, vänta ett tag. Du kompilerar väl även de filer som använder templaten? Templatefilen kan inte kompileras för sig eftersom C++ inte vet hur mycket plats som tas upp av "template-typen".

Mc FettoMedlem sedan nov. 20022 355 inlägg
#5

Nu måste jag säga att jag inte hänger med, i vilken av dina två tidigare ver menar du? Jag försöker få det att fungera på alt. 2 för det känns nyttigt att veta hur man gör det om man sysslar med större projekt än det jag gör! :).

aasahMedlem sedan mars 20034 471 inlägg
#6

Eftersom alternativ 2's cpp fil saknar definitioner - en följd av att du inkluderar cpp:n i h-filen och inte tvärtom kan den filen inte kompileras. Vilket är skälet till att jag brukar köra alternativ 1.

Men det var ett tag sedan jag programmerade med templates och jag minns inte om det går att separatkompilera i alt 1 heller. Rimligen borde det vara samma problem? :q Om du skaffar dig ett litet main som använder din template med en Bok nånstans så borde det däremot funka att kompilera. Då vet ju programmet hur stor plats typen tar eftersom typen blev Bok.

PeWMedlem sedan juni 200010 432 inlägg
#7

aasah skrev:

  1. Lägg all template klass i EN fil. Döp den till .cpp

Varför döpa den till .cpp när det fungerar att ha den som .h ? Det viktiga är (som du redan skrev) att kompilatorn inte vet hur minnet ser ut om man delar upp definitioner och deklarationer med templates och att det således krävs att man lägger allt i samma fil och då som *.h

Men:

deque<T>* minDeque;

Bör väl ge att:

minDeque.push_front(Objekt);

Borde vara:

minDeque->push_front(Objekt);

r
Förutsatt att pekaren pekar på nåt vettigt, förstås ;)

Mc FettoMedlem sedan nov. 20022 355 inlägg
#8

Hm, jaja jafg får det som sagt ändå inte att funger... är rätt trött nu så jag får nog ta och sova på det och köra med ett nytt huvud :) tack för hjälpen i vilket fall :)

PeWMedlem sedan juni 200010 432 inlägg
#9

Hmm... tänk på att templates gör att du som programmerare får ta större ansvar. Kompilatorn förutsätter att du vet vad du gör och sånt som du kanske annars får klagomål om passerar med kryptiska fel i slutändan. Var glad att det nu blev länkfel... det kan i värsta fall bli runtime-fel som är svåra att hitta :l

Mc FettoMedlem sedan nov. 20022 355 inlägg
#10

PeW skrev:

Hmm... tänk på att templates gör att du som programmerare får ta större ansvar. Kompilatorn förutsätter att du vet vad du gör

*host* så jag kan inte svära åt kompilatorn :(

PeWMedlem sedan juni 200010 432 inlägg
#11

Här deklarerar du en pekare:

deque<T>* minDeque;

Men vart är allokeringen av deque som pekaren ska peka på?

*host* så jag kan inte svära åt kompilatorn

Feel free to do whatever you want :) Jag menade mer generellt än i endast detta fall. Här skulle du förmodligen få länkfel även om du inte hade templates.

Mc FettoMedlem sedan nov. 20022 355 inlägg
#12

Oj jag missade ditt första medelande i tråden, ska kolla det nu!

aasahMedlem sedan mars 20034 471 inlägg
#13

PeW skrev:

aasah skrev:

  1. Lägg all template klass i EN fil. Döp den till .cpp

Varför döpa den till .cpp när det fungerar att ha den som .h ? Det viktiga är (som du redan skrev) att kompilatorn inte vet hur minnet ser ut om man delar upp definitioner och deklarationer med templates och att det således krävs att man lägger allt i samma fil och då som *.h ...

Mycket bra fråga! :( :r Det otillfredsställande svaret: Så fick jag lära mig det och jag har - för en gångs skull - inte ifrågasatt det.... Naturligtvis borde man kalla den för .h . Självklart efter påpekandet. :OO

Mc FettoMedlem sedan nov. 20022 355 inlägg
#14

Har gjort som PeW sade att ändra:
minDeque.push_front(Objekt);
till
minDeque->push_front(Objekt);
men jag får fortfarande samma fel, jag hajjar inte vad felet är för fem öre!

PeWMedlem sedan juni 200010 432 inlägg
#15

Men du måste fortfarande allokera för deque.. 'minDeque' är bara en pekare som i ditt fall pekar på okänd adress men pekaren är av typen deque. Förslagsvis så skapar du ett objekt deque, med 'new'-operatorn i konstruktorn för Ko och deletar densamma i destruktorn för Ko. Eller så skippar du pekaren och initierar en variabel 'minDeque' och återgår till '.' - notationen.

Mc FettoMedlem sedan nov. 20022 355 inlägg
#16

Tack PeW men det enda som behövdes var en tom konstruktor. Efter mycket pillande så la jag allt i *.h filen då jag hållt på med samma problem alldeles förlänge :(

Men tack för allt, ni har lärt mig mycket... och hoppas på mer ;)

Mc FettoMedlem sedan nov. 20022 355 inlägg
#17

Tar tillbaka ovanstående om det enda som behövdes... minnet flippade ur så det blir allt en punktnotation :)

PeWMedlem sedan juni 200010 432 inlägg
#18

Glöm inte då att göra om deklarationen av 'minDeque' från pekare till variabel. Dvs ta bort * (stjärna) ... ;)

CoordMedlem sedan okt. 200211 inlägg
#19

aasah skrev:

Jag misstänker att problemet har att göra med uppdelningen i cpp och h fil. Just för templates funkar inte den vanliga valsen med att ha implementationen i cpp och definitionen i h. Det här har nånting att göra med att eftersom klassen är okänd så kan inte minnesåtgången beräknas på bra sätt utifrån definitionen. Finns två sätt att komma runt:

  1. Lägg all template klass i EN fil. Döp den till .cpp
  2. Dela upp på vanligt sätt mellan h och cpp men inkludera bakvänt. Dvs skriv i h-filen efter definitionerna
    # include "my_template.cpp"

(Jag brukar köra på 1, så länge inte koden är jättelång känns det enklast.)

Aha! Tackar, detta var även hjälp för mig :) Har suttit med ett sånt här fel i 6 timmar nu utan att det funkat, och så var det så enkelt att man var tvungen att ha implementationen i samma fil...
Men men, då vet man det i framtiden :)

140 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
137 ms — hämta tråd, inlägg och bilagor (db)