konflikt zwischen statischem und dynamischen Polymorphismus
-
Hallo Leute, ich hab da ne generelle Frage. Hab ein kleines Beispiel für mein Problem zusammengestellt:
#include <iostream> class figure { protected: short m_height; short m_width; public: //getter short height() { return m_height;} //abstract setter virtual void height(short h)=0; }; class rectangle: public figure { public: //setter void height(short h) { m_height=h;} }; class quad: public figure { public: //setter void height(short hw) {m_height=m_width=hw; } }; int main() { //Compiliert: figure* myf=new quad; myf->height(5); std::cout << myf->height() << std::endl; quad* myq=new quad; myq->height(4); /* Das folgende nicht: main.c:43: error: no matching function for call to 'quad::height()' main.c:26: note: candidates are: virtual void quad::height(short int) */ std::cout << myq->height() << std::endl; /* Dies ist ein workaround: */ std::cout << myq->figure::height() << std::endl; return 0; }Es geht darum, Getter und Setter durch statische Polymorphie zu lösen (gleicher Funktionsname, unterschiedliche Signatur)
Wenn nun meine abstrakte Basisklasse eine Getter Methode implementiert, die SetterMethode aber virtuell sind und von den Abgeleiteten Klassen implementiert werden, findet der Compiler die Methode der Basisklasse nicht mehr.
Oben habe ich ein workaround gezeigt, eine andere Möglichkeit wäre es, Setter und Getter virtuell zu machen und von allen Abgeleiteten Klassen implementieren lassen. Das führt natürlich zu doppeltem Code und will ich nicht.
Ahja, die triviale Lösung "GetHeight und SetHeight" gilt nicht

Was für eine Erklärung habt ihr für obiges Verhalten?
Gruß andy :xmas2:
-
Mach einfache Weiterleitungen.
-
David_pb schrieb:
Mach einfache Weiterleitungen.
Na gut, noch ein Work-around.
Ich möchte wissen, ob das nun ein Compilerfehler ist, ob man den Compiler mir irgendwelchen flags so parametrieren kann, dass er das doch versteht, oder ob das man generell statischen und dynamischen Polymorphismus mixen sollte?Gruß Andy
-
Du hast es praktisch herausgefordert, statische Polymorphie, in dem du gleichname Memberfunktionen in deiner Klasse hast. Es ist also dein Entscheidung gewesen, und mußt damit leben. Oder du änderst es.

myq->figure::height() ist ja kein Workaround, es ist ein Sprachmerkmal, mit dem dem explizit eine Funktion in einem anderen Namensraum (in dem Fall figure) benennst. Es ist nichts "schmutziges". Ich halte es aber für den Benutzer der Klasse umständlich. Du könntest den Benutzer unter die Arme greifen, in dem Du heigh() in den abgeleiteten Klassen implementierst und nur weiterleitest.
Aber das Design würde ich unabhängig von dem Problem nochmal überdenken. Dreiecke, Kreise usw. haben zwar eine "virtuelles" viereckige Dimension, aber diese würde ein Benutzer niemals über hight oder width setzen. Für einen Kreis gibt man nen Durchmesser oder Radius an. Dein bisheriges Design ist nicht wirklich zukunftssicher.

Dann würde ich ich über eine Klasse nachdenken, die nur Breite/Höhe anbietet, die für die virtuelle Dimension da ist. (obwohl man die auch on the fly errechnen könnte)
-
wwwAndy schrieb:
Ich möchte wissen, ob das nun ein Compilerfehler ist, ob man den Compiler mir irgendwelchen flags so parametrieren kann, dass er das doch versteht, oder ob das man generell statischen und dynamischen Polymorphismus mixen sollte?
Das hat afaik nichts mit statisch vs. dynamisch zu tun. Das hängt einfach damit zusammen, daß die Überladungs-Auflösung nur innerhalb eines gegebenen Scopes definiert ist - dadurch, daß du eine rectangle::height() definiert hast, werden die Methoden der Basisklasse nicht mehr in die Suche einbezogen.
Zur Lösung kannst du entweder eine Weiterleitung zur Basisfunktion anlegen, den beiden Methoden verschiedene Namen geben oder die Basisfunktion per "using" bekanntmachen.
-
Artchi schrieb:
Aber das Design würde ich unabhängig von dem Problem nochmal überdenken. Dreiecke, Kreise usw. haben zwar eine "virtuelles" viereckige Dimension, aber diese würde ein Benutzer niemals über hight oder width setzen. Für einen Kreis gibt man nen Durchmesser oder Radius an. Dein bisheriges Design ist nicht wirklich zukunftssicher.

Ich habe oben geschrieben: "Habe ein Beispiel für mein Problem zusammengestellt", damit es hier überschaubar bleibt. Die reale Anwendung ist eine Client-Server Geschichte mit CORBA, speziell TAO (The ACE Orb, ACE=Adaptive Communication Environment) und FLTK (www.fltk.org) und hat mittlerweile über 12000 Zeilen Code. Das wollte ich hier nicht posten... Und gerade FLTK verwendet statische Polymorphie für Getter und Setter Methoden, daran kann ich also nichts ändern. Das CORBA Konzept mit C++ hingegen macht massiven Gebrauch von abstrakten Basisklassen und Mehrfachvererbung.
Du verzeihst mir also, dass ich das "Problem" auf ein einfaches Beispiel minimiert habe?
Gruß Andy
-
Achso...
