Brächte Rat bei Klassendesign: Abstrakte Basisklasse etc..
-
Hallo,
im Moment sieht mein code vereinfacht und pseudo so aus:
class Basis { //ein paar funktionen hier die aber nichts //zu meiner frage beitragen protected: virtual void foo() = 0; }; class C1 : Basis { public: protected: virtual void foo(); } class C2 : Basis { protected: virtual void foo(); }Jetzt sollen abhängig von einem user-parameter der grob gesagt die werte 0 - 3 haben kann von der Klasse C2 in der Methode foo() unterschiedliche Dinge passsieren. Z.B Statt der funktion a() die foo() aufgerufen wird, jetzt eine funktion b() aufrufen:
C2::foo() { //.... a() //.. }Thematisch gehörte das aber alles in die Klasse C2 weil die sozusagen wieder so eine art Basisklasse für die 4 verschiedenen parameter.
Ich möchte nicht für 4 parameter ständig if-elsif-elsif-else zweige verwenden und dacht evtl. daran 4 weiter Klassen zu bauen die alle ein spezielles foo() implementieren. Allerdings habe ich dann code 4-fach, bis halt auf ein paar ausnahmen. Wie macht man denn sowas? Sollte man da evlt. die Klasse C2 wieder als Basis für 4 weitere Klassen halten?
Über ANregungen würde ich mich freuen - und ich kann keinen code hier zeigen weil es sonst den rahmen sprengen würde. Also bitte nicht mit solchen antworten. Danke

-
Weiß nicht genau was du willst ... also natürlich kannst du bar(c2) als base nehmen ...
class base { protected: virtual void call() = 0; }; class foo : base { protected: void call(); }; class bar_base : base { protected: virtual void call(); }; class bar : bar_base { protected: void call(); };... oder:
class base { protected: virtual void call() = 0; }; class foo : base { protected: void call(); }; class bar : base { typedef void (base::*fnPtr)() const; enum type { a, b, c, d}; const type m_type; protected: std::map<type, fnPtr> m_calltype; public: bar(type const& call) : m_type(call) {} protected: void call() { (*this.*m_calltype[m_type])(); } }; class bar_derived : bar { public: bar_derived() : bar(a) { m_calltype.insert(std::make_pair(type::a, bar_derived::foo)); } public: void foo() const { std::cout << "bar_derived!" << std::endl; } };
-
Könntest Du vielleicht ein paar Worte verlieren was da im zweiten fall passiert? Function-Pointer?

-
Ach, der schreibt immer so verwirrenden Code

Wenn der Code so ähnlich ist, mach doch einfach eine switch-Unterscheidung. Deshalb solltest du keine 4 neuen Klassen entwerfen, das Konzept von OOP ist das ja nicht gerade.. Ein Kindklasse soll ja zur Elternklasse immer eine Ist-Ein-Beziehung haben und sie sollte vor allem _nötig_ sein

-
Ok - danke....aber:
[quote]mach doch einfach eine switch-Unterscheidung[quote]
wie meinst du das? Meinst du evtl. ich sollte 4mal die methode schreiben mit jeweils der kleinen änderungen aber halt davor in die richtige mit switch verweisen?
Danke
-
Wie der ist doch nicht verwirrend

Function-Pointer?

Nee... das wäre doch zu einfach
Bzw. schon ... aber keine einfachen sondern sog. Method-Pointer.class bar : base { typedef void (base::*fnPtr)() const; // So sollen unsere Funktionen aussehen (void #name () const) ... enum type { a, b, c, d}; // diese Funktionstypen soll es geben ... kannst auch einfach einen Integer odg. nehmen. Ist nur damit du die Funktion eindeutig auswählen kannst. const type m_type; // const und private damit uns keiner mehr dran rumfummelt ... unser aktuelle Funktions-ID protected: std::map<type, fnPtr> m_calltype; // Map in der alle Method-Pointer einer ID zugewiesen sind. public: bar(type const& call) : m_type(call) {} // Im Kontruktor die Method-Pointer-ID festlegen ... protected: void call() { (*this.*m_calltype[m_type])(); } // Aufruf des Method-Pointer, der der aktuellen ID(m_type) zugewiesen ist. // Das ist allerdings nur Pseudocode. Normal musst du hingehen und std::map<...>::iterator it = m_calltype.find(m_type); if (it != m_calltype.end()) (*this.*(it->second))(); nehmen ... // also erst gucken ob überhaupt ein Method-Pointer für diese ID registriert ist ... // wenn ja, soll der Method-Pointer mit dem this-Zeiger aufgerufen werden. };... das zur Erklärung ...
-
puh.....danke.....da fängt man an zu glauben man könnte ein klitzeklein wenig programmieren und dann sowas

-
Allerdings habe ich dann code 4-fach, bis halt auf ein paar ausnahmen. Wie macht man denn sowas?
Denn Teil vom Code der gleich ist ein Unterfunktionen der Basisklasse aufteilen.
-
sehe ich das richtig, dass ich mit den method-pointern einfach nur eine instanz von bar erzeuge und mittels des übergebenen arguments automatisch in dir richtige methode von den derived-klassen springe? oder doch nicht ?

-
Denn Teil vom Code der gleich ist ein Unterfunktionen der Basisklasse aufteilen.
ja das habe ich schon, nur trotzdem sieht es dann so aus:
class derived : basis { protected: virtual void foo() { //basis-funktionen basefunc1(); basefunc2(); basefunc3(); //hier jetzt eben anhand eines parameters: if(param ==1) //und noch weiteres fkta(); elsif (param == 2) //und noch ein paar andere kleinigkeiten fktb(); else fktc(); //basis-fuktionen basefunc4(); basefunc5(); .... } };