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

CBenni::O

1x Contest-Sieger

  • »CBenni::O« ist der Autor dieses Themas

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

1

17.02.2010, 13:21

Template-Klassenmemberfunktionen?

Hallo,
ich möchte eine Art "Priority-Queue" erstellen und benutze dafür natürlich Templates.

Wenn ich nun aber die Klasse folgendermaßen definiere:

PQueue.hpp

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
#include <vector>
#include "PQueueElement.hpp"
#include <iostream>

namespace PQ
{
template <typename T>
class PriorityQueue
{
public:
    void PushElement(T Element, int Priority=0);    // Add a new Element to the queue

    T* PopElement();                            // Get the topmost Element (highest priority, FIFO), deletes it)

    void Clear();                               // delete all Elements out of the Queue

    bool Empty();                               // Check if the Queue is empty

    bool EmptyNotNull();                        // Check if the Queue is empty exept for priority=0 elements

         ~PriorityQueue();
         PriorityQueue();
private:
    typename std::vector<PQ::PQueueElement< T> > Elements;
    typename std::vector<PQ::PQueueElement< T> >::iterator it;
};
}


und dann die Funktionen dazu in PQueue.cpp definiere:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "PQueue.hpp"

namespace PQ
{
template <typename T>
void PriorityQueue<T>::PushElement(T Element, int Priority) // Add a new Element to the queue

{
    // ...

}

template <typename T>
PriorityQueue<T>::PriorityQueue()
{
    std::cout << "PQ wird erstellt!" << std::endl;
    it = Elements.begin();
}

//...


}


Bekomme ich folgende Fehler:

Zitat

1>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall PQ::PriorityQueue<int>::~PriorityQueue<int>(void)" (??1?$PriorityQueue@H@PQ@@QAE@XZ)" in Funktion "_main".
1>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall PQ::PriorityQueue<int>::PushElement(int,int)" (?PushElement@?$PriorityQueue@H@PQ@@QAEXHH@Z)" in Funktion "_main".
1>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: __thiscall PQ::PriorityQueue<int>::PriorityQueue<int>(void)" (??0?$PriorityQueue@H@PQ@@QAE@XZ)" in Funktion "_main".


main.cpp ist nur:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
#include "PQueue.hpp"
#include <iostream>

int main()
{
    PQ::PriorityQueue<int> MyPQ;
    MyPQ.PushElement(5,2);
    return 0;
}


Ich denke, dass etwas mit der Definition meiner Memberfunktionen nicht stimmt... Was mache ich falsch?

EDIT: Achso, und wenn ich die Funktionen noch in die Klassendefinition packe, klappt es...

Danke schon mal im voraus ;)

mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

2

17.02.2010, 13:27

Machst du das zur Übung? Wenn nicht nimm doch den Priority Queue aus der STL, erspart dir die Kopfschmerzen.

idontknow

unregistriert

3

17.02.2010, 13:28

Jo, Templates musst du im Header definieren kA warum :P
Gibt glaub ich (z.b. in der SFML (Rect)) auch iorgendwelche inl files mit denen man das auslagern kann..

CBenni::O

1x Contest-Sieger

  • »CBenni::O« ist der Autor dieses Themas

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

4

17.02.2010, 13:35

Zitat von »"HighligerBimBam"«

Machst du das zur Übung? Wenn nicht nimm doch den Priority Queue aus der STL, erspart dir die Kopfschmerzen.


Naja, mehr oder weniger...

Ich habe mir die aus der STL mal angeschaut und überhaut nicht verstanden... Von daher habe ich so oder so Kopfschmerzen, und so lerne ich dabei wenigstens noch etwas, z.b. wie man Memberfunktionen von Templateklassen außerhalb von der Header-Deklaration (oder eben auch nicht -.-) definieren kann :D

Danke ;)

EDIT: Jetzt klappts :)
Für alle Interessierten: Hier könnt ihr den Sourcecode herunterladen
mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

5

17.02.2010, 13:48

Zitat von »"CBenni::O"«

Von daher habe ich so oder so Kopfschmerzen, und so lerne ich dabei wenigstens noch etwas, z.b. wie man Memberfunktionen von Templateklassen außerhalb von der Header-Deklaration (oder eben auch nicht -.-) definieren kann :D

Das geht nur theoretisch, praktisch ist es extrem schwer, einen Compiler zu bauen, der das kann.
Der Grund ist ganz einfach: Wenn man ein Template benutzt, wird für jeden Typ, mit dem man es benutzt eine Kopie der Klasse erzeugt. Wenn man jetzt den template Code in einer cpp Datei hat, würde diese kompiliert und erst mit dem Linker zum Programm hinzugefügt werden. Das geht aber nicht, da der Compiler beim compilieren der cpp nicht wissen kann, mit welchen Typen das Template in irgendeiner anderen Datei benutzt wird.

-> Man muss Templates komplett im Header definieren. Naja, man kann auch die cpp Datei in den Header inkludieren, d.h. die Definitionen in eine separate Datei packen, das macht die Sache übersichtlicher, spart aber auch keine Kompilierzeit.
Lieber dumm fragen, als dumm bleiben!

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

6

17.02.2010, 13:48

Zitat von »"CBenni::O"«


Ich habe mir die aus der STL mal angeschaut und überhaut nicht verstanden...


Bitte? Das ist doch wohl relativ Idiotensicher: http://www.sgi.com/tech/stl/priority_queue.html

riCo

Treue Seele

Beiträge: 165

Beruf: Student

  • Private Nachricht senden

7

17.02.2010, 13:52

Der Aufbau der "hpp" (warum nicht einfach nur .h ?) ist prinzipiell korrekt.
Du hast nun 3 Möglichkeiten.

1. Entweder du implementierst die Funktionen direkt in der Klasse selbst, was aber die mit Sicherheit schlechteste Variante ist.

2. Du kopierst den Teil deiner cpp und implementierst die Funktionen unterhalb der Klassendefinition.

3. Du kannst die ".cpp" als ".inl" verwenden. Dazu musst du nichts weiter machen, als unter der Klassendefinition im Header die ".inl"-Datei zu includen. Höchstwahrscheinlich wird dir der Compiler dann einen Fehler werfen, weil du keinen Header-Guard verwendest.

Dein Header könnte dann so aussehen(ungetestet):

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
#ifndef __PRIORITYQUEUE_H_INCLUDED__
#define __PRIORITYQUEUE_H_INCLUDED__

#include <vector> 
#include "PQueueElement.hpp" 
#include <iostream> 

namespace PQ 
{ 
template <typename T> 
class PriorityQueue 
{ 
public: 
    void PushElement(T Element, int Priority=0);    // Add a new Element to the queue 

    T* PopElement();                            // Get the topmost Element (highest priority, FIFO), deletes it) 

    void Clear();                                // delete all Elements out of the Queue 

    bool Empty();                                // Check if the Queue is empty 

    bool EmptyNotNull();                        // Check if the Queue is empty exept for priority=0 elements 

         ~PriorityQueue(); 
         PriorityQueue(); 
private: 
    typename std::vector<PQ::PQueueElement< T> > Elements; 
    typename std::vector<PQ::PQueueElement< T> >::iterator it; 
}; 


#include "PQueue.inl"

}

#endif // __PRIORITYQUEUE_H_INCLUDED__
Wir leben alle unter dem Sternenhimmel, aber wir haben nicht alle den gleichen Horizont.

CBenni::O

1x Contest-Sieger

  • »CBenni::O« ist der Autor dieses Themas

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

8

17.02.2010, 13:59

Zitat von »"David_pb"«

Bitte? Das ist doch wohl relativ Idiotensicher: http://www.sgi.com/tech/stl/priority_queue.html


Ja, gut, aber mein Ziel war ein anderes:

Eine Warteschleife, bei der man jedem Element eine Zahl zuweisen kann; je nachdem, wie hoch diese Zahl ist, wird der Stapel abgearbeitet... std::PriorityQueue ist zu Allgemein, soweit ich das verstanden habe, gibt man seine eigene Größer/ Kleiner-Funktion mit an, oder?

Natürlich, man könnte ein workaround dafür machen, aber so ist es doch einfacher :)

mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

9

17.02.2010, 14:03

Oder du nimmst einfach eine Funktion aus der STL. Es kommt halt drauf an was genau deine Vorstellungen sind. Realisieren kannst du dies mit der STL in der Regel einfacher.

CBenni::O

1x Contest-Sieger

  • »CBenni::O« ist der Autor dieses Themas

Beiträge: 1 145

Wohnort: Stuttgart

  • Private Nachricht senden

10

17.02.2010, 14:08

Siehe download ;)

Genauso habe ich mir das vorgestellt... Und ich habe nun doch einfach die Funktionen in der Klassendeklaration definiert... Alles andere ist hier irgendwie overkill; Dennoch merke ich mir diesen Thread mal ;)

mfg CBenni::O
Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.
42!
Aufräumen kann jeder, nur das Genie überblickt das Chaos!
Metal will never die!
1. Sppro Gamecontest - mein Beitrag

Werbeanzeige