Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

15.05.2011, 11:14

Linker wirft nicht lesbaren Fehler

Hallo,

ich habe heut morgen mal mit Templates herumgespielt. Leider wirft der Linker noch ein paar Fehler die mir wirklich nichts sagen...

1>------ Erstellen gestartet: Projekt: Templates, Konfiguration: Debug Win32 ------
1> CJaeger.cpp
1>Main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall CJaeger<float>::auswerten(float)" (?auswerten@?$CJaeger@M@@QAEXM@Z)" in Funktion "_main".
1>Main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall CJaeger<float>::verarbeite(class CHase *)" (?verarbeite@?$CJaeger@M@@QAEXPAVCHase@@@Z)" in Funktion "_main".
1>Main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall CJaeger<float>::CJaeger<float>(void)" (??0?$CJaeger@M@@QAE@XZ)" in Funktion "_main".
1>c:\dokumente und einstellungen\sebastian\eigene dateien\visual studio 2010\Projects\Templates\Debug\Templates.exe : fatal error LNK1120: 3 nicht aufgelöste externe Verweise.
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========

Hat jemand eine Idee woran das liegen kann ? oder wie ich am besten solche Fehler zu verstehen habe?!

lg
Sebastian

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

2

15.05.2011, 11:35

Wie wäre es mit dem betreffenden Code abschnitt/Datei? ;)
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

3

15.05.2011, 11:46

Also ich habe gerade mal testweise alle Templatedefinitionen entfernt und dann funktioniert alles super. Also muss es an dem Template liegen.

Habe gerade nochmals wiederholt mit dem Buch verglichen... sollte jedoch sweit stimmen. Der Fehler muss aber irgendwo in der CJaeger.h , CJaerger.cpp oder Main.cpp liegen.
Templates sind wirklich nicht hübsch, allein schon vom Code overhead ... dass muss man schon sagen ^^

Hier mal mein Sourcecode:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//Header Main.h

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

using namespace std;

#include "Main.h"

int main() {
    CHase *pHase1;
    CHase *pHase2;
    CHase *pHase3;

    CJaeger<float> jaeger;

    pHase1 = new CHase("Fritz", 7676);
    pHase2 = new CHase("Rudolf", 33);
    pHase3 = new CHase("Heinz", 22);

    
    jaeger.verarbeite(pHase1);
    jaeger.verarbeite(pHase2);
    jaeger.verarbeite(pHase3);

    jaeger.auswerten(33);

    delete pHase1;
    pHase1 = NULL;
    delete pHase2;
    pHase2 = NULL;
    delete pHase3;
    pHase3 = NULL;

    
}
//Jaeger.h

#ifndef CJAEGER_H
#define CJAEGER_H
#include "CHase.h"
template <class T>
class CJaeger
{
public:
    CJaeger(void);
    ~CJaeger(void);
    void schiessen(const CHase &hase);
    void verarbeite(CHase *hase);

    void auswerten(T wert);
private:
    static int counter;
    int id;
    T verarbeitet;
};

#endif

//CJaeger.cpp
#include "CJaeger.h"
template <class T>
int CJaeger<T>::counter;

template <class T>
CJaeger<T>::CJaeger(){
    cout << "Initialisiere " << ++counter << endl;
    id = counter;
}

template <class T>
CJaeger<T>::~CJaeger() {
    cout << "Zerstoere " << id << endl;
}
template <class T>
void CJaeger<T>::schiessen(const CHase &hase) {
    cout << "Schiesse: " << endl;
    cout << "Name: " << hase.m_name;
    cout << "Gewicht: " << hase.m_fGewicht;

}

template <class T>
void CJaeger<T>::verarbeite(CHase *hase) {
    cout << "Verarbeite: " << endl;
    cout << "Name: " << hase->m_name << endl;
    cout << "Gewicht: " << hase->m_fGewicht << endl;
    cout << endl;

    hase->m_fGewicht -=200;

    printf("Nachher: %f\n", hase->m_fGewicht);



}

template <class T>
void CJaeger<T>::auswerten(T wert) {
    cout << "Ausgewertet: " << verarbeitet * wert;
}

//CHase.h
#ifndef CHASE_H
#define CHASE_H

#include <iostream>
using namespace std;

class CHase
{
public:
    CHase(char name[], float gewicht);
    ~CHase(void);
    char m_name[64];
    float m_fGewicht;
    
};
#endif
//CHase.cpp
#include "CHase.h"


CHase::CHase(char name[], float gewicht)
{
    for (int i = 0; i < 64; i++) 
    {
        m_name[i] = name[i];

        if(name[i] == '\0')
            break;
    }
}


CHase::~CHase(void)
{
    printf("Hase wurde vergraben.\n");
}


Danke schonmal für deine Mühe

drakon

Supermoderator

Beiträge: 6 513

Wohnort: Schweiz

Beruf: Entrepreneur

  • Private Nachricht senden

4

15.05.2011, 12:10

Templates kannst du nicht in .cpp's auslagern.
Die Definition der Funktion muss ja bekannt sein, damit der Compiler generieren kann. Du kannst die templates direkt in der Klassendefinition implementieren oder aber auch einfach die Implementierung, wie du sie jetzt hast in den Header kopieren.

Fred

Supermoderator

Beiträge: 2 121

Beruf: Softwareentwickler

  • Private Nachricht senden

5

15.05.2011, 12:18

Template-Klassen und deren Funktionen müssen in ihreren Header-Dateien definiert werden. Die Funktionen aus Jaeger.cpp müssen also in die Jaeger.h Datei.
Es gäbe auch noch die Möglichkeit, die Definitionen in eine andere Datei einzubinden(Nach Möglichkeit weder cpp noch h) und diese dann per include am Ende der Klassendeklaration einzubinden.

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

6

15.05.2011, 12:31

Templates sind wirklich nicht hübsch, allein schon vom Code overhead ... dass muss man schon sagen


Templates sind mit das tollste, was es an C++ gibt. Mit ihnen kannst du dir sehr viel Arbeit sparen, wenn du beispielsweise die selben Aufgaben mit unterschiedlichen Datentypen ausführen willst.

Architekt

Community-Fossil

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

7

15.05.2011, 12:34

Ich glaub seine Aussage geht nicht gegen Templates an sich und ihre Funktionalität, sondern vielmehr, dass man relativ viel Code schreiben muss, um eine Funktion/Methode als Template zu deklarieren.
Also template<typename T>.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

8

15.05.2011, 13:22

Wenn man nun ein Interface an jemanden geben möchte, übergibt man ja in der Regel nur die Headerdateien. Wie geht man denn dann bei den Templates vor, wenn man solch ein Interface bereitstellen möchte?

LG
Sebastian

PS: funktioniert übrigens super ! :) danke!

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Akrillo« (15.05.2011, 13:32)


9

16.05.2011, 12:28

Du schreibst den kompletten Code in die Headerdatei. Wenn dir das zu hässlich wird kannst du die Definition ja auslagern und unten an die Header datei mit #include einbinden. Ansonsten wenn du viele verschiedene Instanzen von deinem Template hast, kannst du auch bestimmte template instanzen separat kompilieren und dann später linken - das macht nur dann Sinn wenn du weißt welche Instanziierungen du brauchst, und wenn das erstellen der Instanzen die Kompilierzeit stark beeinträchtigt. ( http://msdn.microsoft.com/en-us/library/…=VS.100%29.aspx )

Werbeanzeige