Funktionspointer einer Klasse übergeben
-
Hallo,
ich habe das Problem, dass ich bei einer generischen Klasse den Typ als Funktionsparamenter nicht übergeben kann.
Sobald ich aber in der Klasse UtlList die Funktion Sort wiefolgt abändere: "void Sort(int (*pFunc)(const TestClass*, const TestClass*))" und den entsprechenden Header beifüge, funktioniert es einwandfrei.
Aber mein Ziel ist es das ganze über: "void Sort(int (*pFunc)(const E*, const E*))" zu machen, damit das ganze weiterhin generisch bleibt.
Hier mein Code:
UtlList.h
template <class E> class UtlList { public: void Sort(int (*pFunc)(const E*, const E*)) { ... } };TestClass.h
class TestClass { public: TestClass(void); TestClass(int test); static int SortTest(const TestClass* a, const TestClass* b); int test; };TestClass.cpp
int TestClass::SortTest(const TestClass* a, const TestClass* b) { if(a->test == b->test) { return 0; } else if(a->test < b->test) { return -1; } else { return 1; } }Main.cpp
int main(int argc, char** argv) { UtlList<TestClass*> list; TestClass* t1 = new TestClass(4); TestClass* t2 = new TestClass(5); list.Add(t1); list.Add(t2); list.Sort(TestClass::SortTest); }Hat jemand eine Idee oder einen Alternativvorschlage?
Vielen Dank.
Gruß, TrAx
-
UtlList<TestClass*> list; // Main.cpp, Zeile 2Mach mal das Sternchen weg.
-
Nur mal so prinzipiell: Wieso nicht std::list bzw. std::sort?
Abgesehen davon, liegt das Problem hier:
void Sort(int (*pFunc)(const E*, const E*))Dein E ist bereits TestClass*, E* entspricht also nicht TestClass*, sondern TestClass**...
-
Sone schrieb:
UtlList<TestClass*> list; // Main.cpp, Zeile 2Mach mal das Sternchen weg.
Vielen Dank! Funktioniert!
Kann man das Ganze auch so abändern, dass man in der UtlList dennoch Pointer verwendet?
-
trax1988 schrieb:
Sone schrieb:
UtlList<TestClass*> list; // Main.cpp, Zeile 2Mach mal das Sternchen weg.
Vielen Dank! Funktioniert!
Kann man das Ganze auch so abändern, dass man in der UtlList dennoch Pointer verwendet?
Wie abändern?
Wenn du einen Zeiger willst, dann gibst du das so an... (E*)... ^^
-
dot schrieb:
Nur mal so prinzipiell: Wieso nicht std::list bzw. std::sort?
Weil ich das gleiche mal in Java implementiert habe und vorallem aus Lernzwecken nochmal implementiert.
dot schrieb:
Abgesehen davon, liegt das Problem hier:
void Sort(int (*pFunc)(const E*, const E*))Dein E ist bereits TestClass*, E* entspricht also nicht TestClass*, sondern TestClass**...
That means ^^?
-
trax1988 schrieb:
Kann man das Ganze auch so abändern, dass man in der UtlList dennoch Pointer verwendet?
Tust du doch. Du nutzt ja schließlich
E*undEist bei dir nunTestClass. Der Fehler war ja gerade, dass du vorherTestClass*alsEhattest und somitTestClass**alsE*. wenn duTestClass*als Templateparameter benutzen möchtest, darfst du entsprechend nurEbenutzen, wenn duTestClass*meinst.Was hast du überhaupt vor? Was ist der Sinn hiervon? Wenn wir das wissen, können wir dir auch besser helfen, als nur die technisch korrekte Antwort auf deine Fragen zu geben.
edit: Ahh, du hast schon geantwortet:
trax1988 schrieb:
Weil ich das gleiche mal in Java implementiert habe und vorallem aus Lernzwecken nochmal implementiert.
Häng dann nicht zu sehr an Java-Strukturen. C++ ist nicht Java und versuchen, in C++ Java zu programmieren ist meistens nicht so toll. Das sieht man zum Beispiel an dem new in deiner main: Typisch Java, in C++ würde man das falsch nennen (auch wenn es technisch gesehen compiliert), weil man es sehr leicht (ja sogar leichter als es derzeit ist) besser machen könnte.
In C++ würde man das typischerweise auf Art der schon genannten std::list bzw. std::sort implementieren, wenn man diese aus irgendeinem Grunde nicht benutzen möchte. Apropos: Gibt es einen Grund, diese nicht zu benutzen?
-
Ich habe eine eigene UtlList Klasse geschrieben, die soweit schon sehr gut funktioniert. Nun sitze ich am eigenen sortieren, mit vorgegeben Funktionen. Man soll also durch eine Funktion den Schlüsselwert für 2 Vergleiche aufstellen in einer Klasse. Also, wenn z.B. der Wert test (integer) gleich der anderen Klasse ist wird 0 zurück gegeben, ist er kleiner -1 und wenn größer, dann 1.
Die Sort-Funktion soll dann eben anhand dieser Werte die Liste sortieren mit QuickSort.
-
trax1988 schrieb:
dot schrieb:
Abgesehen davon, liegt das Problem hier:
void Sort(int (*pFunc)(const E*, const E*))Dein E ist bereits TestClass*, E* entspricht also nicht TestClass*, sondern TestClass**...
That means ^^?
Der Template-Parameter E steht für den Typ den du in der Template-Parameterliste dafür angibst.
Wenn du in der Parameterliste
TestClass*angibst, dann steht E auch fürTestClass*, und wenn du irgendwoE*stehen hast, dann wird darausTestClass**.Hast du Templates überhaupt verstanden?
-
Sone schrieb:
trax1988 schrieb:
dot schrieb:
Abgesehen davon, liegt das Problem hier:
void Sort(int (*pFunc)(const E*, const E*))Dein E ist bereits TestClass*, E* entspricht also nicht TestClass*, sondern TestClass**...
That means ^^?
Der Template-Parameter E steht für den Typ den du in der Template Parameterliste dafür angibst.
Wenn du in der Parameterliste
TestClass*angibst, dann steht E auch fürTestClass*, und wenn du irgendwoE*stehen hast, dann wird darausTestClass**.Hast du Templates überhaupt verstanden?
Scheinbar noch nicht, aber ich verstehe so langsam, was damit gemeint ist.
-
So, habe das ganze jetzt abgeändert und es funktioniert auch mit Pointer.
Vielen Dank für die Lösungsansätze.
-
Da du dich eh schon in einer Klassen-Template befindest, dürfte es kein großes Problem darstellen, Sort zu einer Funktions-Template zu machen:
template<typename Compare> void Sort(Compare comp) { // Sortierung hier. Ordnung ist durch comp(obj1, obj2) definiert. } void Sort() { Sort(std::less<E>()); }...so macht das beispielsweise auch std::list. Der Vorteil ist, dass du so nicht nur Funktionen, sondern auch Funktoren (d. h. Objekte, deren Klassen einen passenden operator() haben) als Ordnung benutzen kannst.
-
seldon schrieb:
Da du dich eh schon in einer Klassen-Template befindest, dürfte es kein großes Problem darstellen, Sort zu einer Funktions-Template zu machen:
template<typename Compare> void Sort(Compare comp) { // Sortierung hier. Ordnung ist durch comp(obj1, obj2) definiert. } void Sort() { Sort(std::less<E>()); }...so macht das beispielsweise auch std::list. Der Vorteil ist, dass du so nicht nur Funktionen, sondern auch Funktoren (d. h. Objekte, deren Klassen einen passenden operator() haben) als Ordnung benutzen kannst.
Interessant. Werde ich so abändern und nutzen. Danke!
-
Am Rande: Was ist denn so falsch daran, Objekte in der main so zu erzeugen? Wie könnte man es besser machen? In dem C++ Tutorial wurde es so beschrieben. Unterschiede dabei liegen im Heap und im Stack.
-
trax1988 schrieb:
Am Rande: Was ist denn so falsch daran, Objekte in der main so zu erzeugen? Wie könnte man es besser machen? In dem C++ Tutorial wurde es so beschrieben. Unterschiede dabei liegen im Heap und im Stack.
In C++ gibt es keine Garbage Collection. Selbst Speicher verwalten ist furchtbar anstregend.
Stackobjekte wo es nur geht, selbst Speicher verwalten sollte gänzlich vermieden werden
-
TestClass gurke; // <- dies erzeugt ein Objekt, nicht wie in Java!!
-
Achso. Ja, dass es keinen Garbage Collector gibt, weiss ich. Aber dafür kann man dynamische Objekte auch löschen mit delete.
Aber danke für den Hinweis.
-
Ich hätte da noch eine letzte Frage, wofür ich keinen neuen Thread aufmachen will.
Ich würde gerne mit Macros, z.B. "#define REGISTER_CLASS(CLASSNAME, PARENT)" innerhalb einer Klasse, die von einer anderen erbt, eine Instanz erzeugen und diese entsprechen in einen Vektor speichern.
Ich habe also einen Vektor von der Elternklasse, also "vector<CInput*> m_inputFacory;". Sobald eine Kindsklasse deklariert ist, und mann z.B. das Macro mit "REGISTER_CLASS(CInputKind, CInput), soll in der Factory davon eine Instanz erzeugt werden und in den Vektor gespeichert werden.
Ich habe mir schon ein paar Beispiele angeschaut, aber keines davon trifft auf meines zu.
Jemand eine IDee, wie man das am besten umsetzen kann?
Vielen Dank!
-
trax1988 schrieb:
Ich hätte da noch eine letzte Frage, wofür ich keinen neuen Thread aufmachen will.
Für jedes neue Thema bitte auch ein Thread!
-
asc schrieb:
trax1988 schrieb:
Ich hätte da noch eine letzte Frage, wofür ich keinen neuen Thread aufmachen will.
Für jedes neue Thema bitte auch ein Thread!
Alles klar.