Polymorphie und Vererbung
lima-city → Forum → Programmiersprachen → C/C++ und D
absturz
bereich
button
code
dank
double
element
entscheidende punkt
erreichen
instanz
leeren funktionen
list
methode
operator
private element
programm
risiko
speicherung
studieren
zeiger
-
Hi.
Ich habe in meinem Spiel eine kleine Klasse für die GUI. Diese ist die Elternklasse für alle GUI-Elemente
class GUI { private: Element **element; public: processMouseClick() { int i; for (i =0;i<10;i++) { element[i]->processMouseClick(); } } };
Die Klasse Element ist dabei die Elternklasse aller GUI-Elemente. Diese beinhaltet sämtliche Methoden, die mindestens ein GUI-Element hat als leere Prototypmethoden:
class Element { public: void processMouseClick() { } };
Wenn ich nun ein Element wie z.B. einen Button in der Variable **element abgespechert habe möchte ich natürlich, dass die Methode processMouseClick der Klasse Button ausgeführt wird. Dazu habe ich das Schlüsselwort virtual entdeckt. Wenn ich dieses aber verwende werden die leeren funktionen nicht mehr weitervererbt, sondern das Programm stürzt ab, sollte die Klasse Button nicht über die Methode processMouseClick verfügen.
Wie kann ich es nun erreichen, dass die Methode der Kindklasse gewählt wird, sollte diese vorhanden sein, oder ansonsten die Methode der Elternklasse vererbt wird?
Danke schonmal
Dustboy
Beitrag zuletzt geändert: 24.1.2011 22:35:18 von dustboy -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
normalerweise sollte es mit virtual gehen.
virtual erstellt zur laufzeit einen virtuellen table mit den late bindings, sodass auf die tatsächliche instanz eingegangen wird, und nicht auf die abstammung des ganzen wie beim early binding.
aber der prototyp von element sollte trotz allem so aussehen:
class Element : public GUI {
sonst wird ja nichts vererbt. aber auf diese fehler möcht ich nu garnicht eingehen^^
virual ist schon die richtige art und weise. gib mal bitte den exakten quellcode, mit dem du diese vererbung durchtreibst, damit man den mal studieren kann, weshalb es nicht stimmt. (zumindest die betroffenen ausschnitte) das würde sehr helfen =) (mir zumindest) -
Also hier mal aufs relevante beschränkt (unten werd ich auch noch einen Downloadlink zur ungekürzen Fassung bereitstellen. Wäre hier in Textform aber sicher unübersichtlich):
#include "element.h" class GUI { private: Element **element; public: void processMouseMove(int mousex, int mousey) { for (int i = 0;i < MAXELEMENTS;i++) { element[i]->processMouseMove(mousex, mousey); } } };
class Element { public: virtual void setPos(double tx, double ty) {} virtual void processMouseMove(int mousex, int mousey) {} };
#include "element.h" class Button : public Element { private: double x, y; public: void setPos(double tx, double ty) { x = tx; y = ty; } };
Wenn ich nun in der Klasse Klasse Element die Methode setPos mit dem Schlüsselwort virtual versehe funktioniert alles wie geplant (die Methode der Klasse Button wird ausgeführt). Versehe ich die Methode processMouseMove mit dem Schlüsselwort virtual, stürzt das Programm beim Methodenaufruf ab. Ich tippe mal, dass das passiert, weil die Methode nicht in der Klasse Button explizit deklariert wurde. Nun möchte ich aber erreichen, dass die Methode der Elternklasse aufgerufen wird, sofern diese in der Kindklasse nicht vorhanden ist.
Natürlich könnte ich einfach die ganzen Methoden leer in den Kindklassen implementieren, aber das würde zum einen viel Aufwand bedeuten und zum anderen eine riesige Fehlerquelle bergen. Außerdem bin ich mir sicher, dass es da eine sauberere Lösung gibt...
So und hier noch die versprochene Komplettfassung der Dateien (falls das oben angegebene nicht ausreicht ):
*link entfernt, weil problem gelöst*
MfG
Dustboy
Beitrag zuletzt geändert: 25.1.2011 22:40:04 von dustboy -
Hallo dustyboy,
ich habe hier ein kleines Beispiel, das zumindest zeigt, dass Du das mit dem 'virtual' schon richtig verstanden hast und der Grund für den Absturz woanders sein muss:
#include <iostream> using namespace std; class parent { public: virtual void method1(int x, int y) {} virtual void method2(int x, int y) {} }; class child: public parent { private: int x; int y; public: void method1(int x, int y) { this->x = x; this->y = y; } friend ostream& operator<<(ostream& os, const child& c); }; ostream& operator<<(ostream& os, const child& c) { os << "[" << c.x << "; " << c.y << "]"; return os; } void call_method1(parent * p) { p->method1(1,2); } void call_method2(parent * p) { p->method2(3,4); } int main() { child *c; c = new child(); call_method1(c); call_method2(c); cout << *c << endl; delete c; return 0; }
Das Beispiel sollte einwandfrei laufen. Da ich jetzt leider kein 7zip zur Hand habe, kann ich Dir nur empfehlen mal mit dem Debugger durchzugehen und alle Zeiger und Schleifengrenzen durchzuschauen (bist Du sicher, dass Du MAXELEMENTS Instanzen hast?)
Edit:
Ein kleiner Tipp: Verwende zur Speicherung Deiner GUI-Elemente lieber std::list oder std::vector, dann sparst Du Dir die Array-Verwaltung und verringerst das Risiko bei Schleifen den gültigen Bereich zu verlassen.
Beitrag zuletzt geändert: 25.1.2011 21:04:43 von darkpandemic -
Der Hinweis mti MAXELEMENTS war der entscheidende Punkt. Es liag zwar nicht daran, dass ich über den Bereich hinausgeschossen wäre, allerdings waren in elements[] die meisten Elemente uninstanziert, was den absturz verursacht hatte. Jetzt läufts, wie es soll.
Danke euch beiden
Dustboy
(Das mit list und vector werde ich mir mal anschauen...) -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage