Template Method Pattern anstatt if-else?
-
Doch, natürlich. Je nach dem was dir konkret vorschwebt ist das entweder sinnvoll oder kontraproduktiv.
-
Hmm naja, ich will einfach nur ein switch - statement einbauen um mir halt den Pointer zurückzugeben.
Also praktich diese Methode:
class1* make_class1( bool input_param ) { if (input_param) // (input_param == true) ist so sinnvoll wie (((((input_param == true) == true) ... ))) return new class1_variante1; else return new class1_variante2; };In die Abstrakte Klasse setzen.
Nur bekomme ich das so nicht hin.
Meine header sehen so aus:
//Class_Base //hier will ich die Header Class_Variante1 und Class_Variante2 einfügen aber // es will nicht. #include "Class_Variante1" #include "Class_Variante2" class Class_Base { public: Class_Base* get(int opt) { switch(opt) { case 0: return new Class_Variante1(); case 1: return new Class_Variante2(); } } } //Class_Variante1 #include "Class_Base" class Class_Variante1 : public Class_Base {...}; //Class_Variante2 #include "Class_Base" class Class_Variante2 : public Class_Base {...};
-
Die abgeleiteten Klassen können nicht definiert werden, bevor die Basisklasse bekannt ist. Für die Konstruktion eines Objektes brauchst du aber die vollständige Definition. Folglich kannst du die Erzeugungsmethode mit den new-Aufrufen nicht direkt im Klassenkörper definieren, sondern nur außerhalb (nachdem die abgeleiteten Klassen definiert wurden).
Praktisch also im cpp-File. Das ist auch von den Abhängigkeiten her sinnvoller.
-
Finix,
du sagst, das TMP habe nichts mit Templates zu tun und gehst dann dazu über, mit virtuellen Funktionen um Dich zu schmeißen. Da muss ich Einspruch erheben, denn das TMP lässt sich natürlich vorzüglich mit Templates umsetzen – und in C++ würde ich im Zweifelsfall immer diese Methode verwenden, statt virtueller Funktionen.
Dass diese Methode in einem Thread im C++-Forum nicht einmal erwähnt wird, finde ich schade.
-
Also mich würde brennend interessieren wie das über Templates realisierbar wäre Konrad. Könntest Du vielleicht den vorig geposteten Beispielcode (so schlimm er auch ist) evtl. über Templates ins TMP packen?
Und was ist der Grund warum über Templates das TMP "besser" ist als über virtuelle Funktionen ?
Praktisch also im cpp-File. Das ist auch von den Abhängigkeiten her sinnvoller.
wenn ich gleichzeitig mit Templates arbeite - ist das dan auch möglich?
Weil sowas in ne cpp-zu schreiben geht ja net:template <class T> Class_Base<T>* Switch_Algorithm<T>::Get_Algorithm(const int opt_level) { switch(opt_level) { case no_opt: return new C1<T>(); case opt_1: return new C2<T>(); } }Könnte es sein, dass ich hier nicht drumrumkomme die Get_Algorithm in ne eigene Klasse bzw. in eine andere Klasse zu packen?
Danke
-
das würde ich auch gerne sehen. ging es dem threadstarter nicht darum, zur laufzeit zu entscheiden, was verwendet werden soll. c++ templates werden doch zur compilezeit festgelegt, wie können die virtuelle funktionen ersetzen?
-
Zur obigen Frage mittels der vermeideung von virtuellen Funktionen habe ich folgenden Thread gefunden:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-192539-and-view-is-next.htmlNur was da der vorteil sein soll weiß ich (noch) nicht. Evtl. sind die Kosten um virtuelle Funktionen aufzurufen etwas teurer bezüglich Zeit?
Ich hätte da noch eine Frage und
ich weiß jetzt nicht ob ich deswegen einen neuen Thread aufmachen soll, deswegen poste ich lieber hier weil es könnte sein dass es eher hier her gehört:ich würde gerne folgenden Code so "vereinfachen", dass das switch statement entfällt. Nun bin ich mir nicht sicher ob es überhaupt geht - evtl. irgendwie über virtuelle Funktionen oder so?
Matrix<double> *A_REAL = NULL; Matrix<COMPLEX> *A_COMPLEX = NULL; switch(o_rm.Get_Type(file)) { case real: { std::cout << "\t Input is REAL!" << std::endl; o_rm.Read_Matrix(file, &A_REAL); // Mache was mit A_REAL; delete A_REAL; break; } case complex: { std::cout << "\tInput is COMPLEX" << std::endl; o_rm.Read_Matrix(file, &A_COMPLEX); // mache was mit A_COMPLEX delete A_COMPLEX; break; }In Read_Matrix gibt es Template-Spezifikationen, die unterschiedlich vom Template, die Matrix unterschiedlich aufbauen. Braucht ihr noch mehr Informationen?
Ich kann also erst zur Laufzeit entscheiden welches Template benutzt wird...
Das ganze läuft in meiner main(), also in keiner Template Klasse
-
ja schrieb:
ging es dem threadstarter nicht darum, zur laufzeit zu entscheiden, was verwendet werden soll.
Das lese ich nirgendwo. Wenn das der Fall ist, sind Templates in der Tat nich geeignet.
Mati schrieb:
Und was ist der Grund warum über Templates das TMP "besser" ist als über virtuelle Funktionen ?
Erstmal, weil es der C++-ige Weg wäre (so arbeitet ja auch die STL, wo möglich). Außerdem ist die Methode wesentlich effizienter als die über virtuelle Funktionen, weil die Auflösung eben zur Compilezeit und nicht zur Laufzeit geschieht.
Der Code sähe prinzipiell genauso aus, nur dass die Funktionen nicht virtuell gemacht werden und die Ziel-Klasse parametrisiert wird.
struct Algorithm1 { void Method1() {} void Method2() {} } struct Alg2 { void Method1() {} void Method2() {} } void my_method<T>(T const& algorithm) { algorithm.Method1(); // … was anderes … algorithm.Method2(); } // Aufruf: if (flag) my_method(Algorithm1()); else my_method(Alg2());
-
hmm...wie viel Zeit kostet denn der aufruf virtueller funktionen im vergleich?
Ist das nur marginal oder doch "zu spüren".
Bei mir würde es nur einmal passieren.Ich schaffe es leider über Templates nicht so ganz:
template <class T> class Algorithm1 { public: void Method1() {} void Method2() {} }; template <class T> class Alg2 { public: void Method1() {} void Method2() {} }; template<class T> T* Algorithm::Get_Algorithm(const int opt_level) { switch(opt_level) { case 0: return new Algorithm<T>(); case 1: return new Alg2<T>(); } } Base<T>::my_method(T* algorithm) { algorithm->Method1(); // … was anderes … algorithm->Method2(); } // in der main: Algorithm<double> o_alg; Base<double> o_base; o_base.my_method(o_alg.Get_Algorithm(0));mein error:
Fehler: »C<double>*« kann nicht nach »double*« in return umgewandelt werden main.cpp:154: instantiated from hereSchon klar der feher aber wie kann ich denn den switch in eine eigene Klasse packen um von dort den richtigen klassentyp zu returnen?
-
Konrad Rudolph schrieb:
Finix,
du sagst, das TMP habe nichts mit Templates zu tun und gehst dann dazu über, mit virtuellen Funktionen um Dich zu schmeißen. Da muss ich Einspruch erheben, denn das TMP lässt sich natürlich vorzüglich mit Templates umsetzen – und in C++ würde ich im Zweifelsfall immer diese Methode verwenden, statt virtueller Funktionen.
Dass diese Methode in einem Thread im C++-Forum nicht einmal erwähnt wird, finde ich schade.
Hier nochmal zum Mitschreiben: das Template Method Pattern hat nichts mit Templates zu tun! Es geht darum dass TMP != Templates und vor allem auch TMP != Template Technik.
Und in C++ stehst du nun mal oft nicht vor dem "Zweifelsfall" sondern vor Limitierungen der Sprache - sollte ich mich täuschen, wäre ich dir sehr verbunden würdest du mir deine Variante, rein mit Templates, in diesem Fall ("über ein input-flag an und ausschaltbar"), vorstellen.
-
Konrad Rudolph schrieb:
ja schrieb:
ging es dem threadstarter nicht darum, zur laufzeit zu entscheiden, was verwendet werden soll.
Das lese ich nirgendwo. Wenn das der Fall ist, sind Templates in der Tat nich geeignet.
ich hätte es so verstanden, weil er sich über die vielen if-else beschwert hat.
@Mati
Für dein switch Problem könnte das State Pattern was sein.
-
Danke ja - aber um ehrlich zu sein bin ich mir (egal wieviel ich übers state pattern lese) nicht sicher obs gehen wird...ich brauch auch immer einen beispielcode...ich suche schon danach aber sinnvolle einfache C++ bespiele zum state pattern finde ich nicht - wäre nett wenn mir jemand helfen könnte.
-
Mati schrieb:
ich suche schon danach aber sinnvolle einfache C++ bespiele zum state pattern finde ich nicht - wäre nett wenn mir jemand helfen könnte.
Du kennst google?
Du weißt wie man Suchworte in google einsetzt?Such mal nach: State Pattern C++
Und wenn du da wirklich nichts findest (bezweifel ich wenn ich das Überblicke), dann kannst du gerne weiter fragen... (Hinweis: selbst mit state muster c++ und Einschränkung auf deutsche Seiten wird man fündig...)
cu André
-
Mati schrieb:
ich suche schon danach aber sinnvolle einfache C++ bespiele zum state pattern finde ich nicht - wäre nett wenn mir jemand helfen könnte.
Wie wäre es hiermit: http://en.wikipedia.org/wiki/State_pattern
-
Hallo?
Ich sagte bereits:sinnvolle einfache C++ bespiele zum state pattern finde ich nicht
unter google finde ich nur umfangreiche und nicht gerade erklärende beispiele.
Aber gut - damit muss ich wohl leben.
-
Mati schrieb:
Praktisch also im cpp-File. Das ist auch von den Abhängigkeiten her sinnvoller.
wenn ich gleichzeitig mit Templates arbeite - ist das dan auch möglich?
Nein, dann natürlich nicht (außer mit export etc. blahblah). Das entscheidende ist, dass der Ctor außerhalb der Klasse base definiert sein muss.
class Base { public: Base(); }; // ich schreib hier die Klassendefinition direkt hin, bei dir wäre ein // #include "derived.h" an dieser Stelle class Derived : public Base { public: Derived() { blub(); } }; // jetzt ist Derived erst bekannt und kann konstruiert werden Base::Base() { new Derived() ... }
-
Ok, dann versuche ich eine konkrete Frage zu stellen:
Ich bin mir nicht sicher ob ich missverstanden wurde. Ich will in der main() einen Template - Typ zurückbekommen, der anhand eines int-werts entweder double oder COMPLEX ist.
Ich kann ja aus der main keine Templates initialisieren. Also sowas geht ja in der main nicht:
Abstract_Matrix ab_mat; // 0 für real // 1 für complex Matrix<T>* matrix = ab_mat.Get_Type(0); //in der Abstract_Matrix template <class T> class Abstract_Matrix { public: T* Get_Type(int c) { if (c) return new Matrix<double>; else return new Matrix<COMPLEX>; } };so ist es ja alles schwachsinn.
Nach diesem Satz:
This is a clean way for an object to partially change its type at runtime.Unter diesem Link:
http://en.wikipedia.org/wiki/State_patterngibt es die folgenden Methoden:
selectPenTool() { currentTool.reset(new PenTool); } selectSelectionTool() { currentTool.reset(new SelectionTool); }Allerdings ist mir schleierhaft wie ich denn einen Template-Basierten DrawingController bauen sollte, der seinen Template-Typ von double nach COMPLEX ändert bzw. wechseln braucht er ja nicht mal. Er braucht ihn ja nur zu initialisieren....
-
Wie schon mehrfach angedeutet, mit einem rein Template-basiertem Ansatz kannst du da zur Laufzeit nicht viel machen.
Davon abgesehen hast du dich mit deinem Matrix-Beispiel, relativ gesehen, kilometerweit von deinem Ausgangsproblem entfernt.
So kann dir nicht nur keiner wirklich helfen, irgendwann fühlen sich die Leute auch ein wenig verarscht. Wenn du Verständnisprobleme mit einem der Pattern hast und diesbezüglich Erleuchtung suchst, mach das deutlich und öffne einen neuen Thread dazu. Wenn du Hilfe zu deinem konkreten Problem suchst, dann leg endlich mal dar was du überhaupt machen willst.
-
Wie schon mehrfach angedeutet, mit einem rein Template-basiertem Ansatz kannst du da zur Laufzeit nicht viel machen.
So etwas wollte ich wissen - mehr nicht.
Davon abgesehen hast du dich mit deinem Matrix-Beispiel, relativ gesehen, kilometerweit von deinem Ausgangsproblem entfernt.
So kann dir nicht nur keiner wirklich helfen, irgendwann fühlen sich die Leute auch ein wenig verarscht.Ich habe geschrieben, dass ich ein weiteres Problem habe, wo ich nicht sicher bin ob es evtl. über Patterns lösbar wäre, evtl. sogar über das TMP. Deshalb hier gepostet.
Wenn man neue Threads aufmacht wird man angeschnauzt man öffne für dieselben Probleme ständig neue Threads.
Wenn man in gleichen Threads arbeitet genauso - also was nun?Wenn du Verständnisprobleme mit einem der Pattern hast und diesbezüglich Erleuchtung suchst, mach das deutlich und öffne einen neuen Thread dazu.
Mit so einem Threas käme als Antwort: Schau bei google oder benutze die Suchfunktion. Auf solche Antworten kann ich verzichten - so ein Thread bringt überhaupt nichts.
Wenn du Hilfe zu deinem konkreten Problem suchst, dann leg endlich mal dar was du überhaupt machen willst.
Mein konkretes problem habe ich dargestellt. Das kann mir nicht angekreidet werden. Vorgeworden werden kann mir nur, dass ich mich sehr unverständlich ausgedrückt habe.
-
Mati schrieb:
Ich habe geschrieben, dass ich ein weiteres Problem habe, wo ich nicht sicher bin ob es evtl. über Patterns lösbar wäre, evtl. sogar über das TMP. Deshalb hier gepostet.
Wenn man neue Threads aufmacht wird man angeschnauzt man öffne für dieselben Probleme ständig neue Threads.
Wenn man in gleichen Threads arbeitet genauso - also was nun?Tatsächlich. Hatte's zuvor nur überflogen - sah so aus als ginge es um das selbe Problem, insbesondere weil's danach wieder nahtlos zum Ursprungsproblem überging.
Ist halt schon praktischer für verschiedene Fragen verschiedene Threads zu öffnen. Da wird auch sicher niemand meckern.
Mati schrieb:
Wenn du Verständnisprobleme mit einem der Pattern hast und diesbezüglich Erleuchtung suchst, mach das deutlich und öffne einen neuen Thread dazu.
Mit so einem Threas käme als Antwort: Schau bei google oder benutze die Suchfunktion. Auf solche Antworten kann ich verzichten - so ein Thread bringt überhaupt nichts.
Definiere "so ein Thread". Wenn du nur mit einem "das XY funzt bei mir nich?!!1" ankommst, dann klar, so was wird zerrissen. Ein "Ich habe mir unter [link] das XY-Pattern angeschaut und verstehe [irgendeinen Punkt] nicht" o.ä. wird da ganz anders aufgenommen.
Mati schrieb:
Mein konkretes problem habe ich dargestellt. Das kann mir nicht angekreidet werden. Vorgeworden werden kann mir nur, dass ich mich sehr unverständlich ausgedrückt habe.
Siehe oben. Ich dachte die Matrix-Geschichte gehört irgendwie dazu, ist das eigentliche Problem oder gar nur ein anderes, potentiell unverwandtes Beispiel.
