Constructor der Abstrakten Vorfahrklasse aufrufen
-
Hiho,
Ich habe ein kleines C++ Anfänger Problem:Ich habe eine Vorfahrenklasse:
class CInterfaceObject { ... public: CInterfaceObject(void); CInterfaceObject(float X, float Y, float Width, float Height, CInterfaceObject* Parent); ~CInterfaceObject(void); virtual void Tick(boolean &ProcessInput) abstract; };
Wie man sieht eine abstrakte Klasse aber der Konstruktor ist implementiert.
Nun habe ich eine Weitere Abstrakte Klasse(implementiert Tick auch nicht):
class CInterfaceComponent : public CInterfaceObject { ... public: CInterfaceComponent(float X, float Y, float Width, float Height, anchor ChildAnchor, anchor ParentAnchor, CInterfaceObject* Parent); CInterfaceComponent(void); ~CInterfaceComponent(void); };
Hier die Implementationen der Konstruktoren:
CInterfaceObject::CInterfaceObject(float X, float Y, float Width, float Height, CInterfaceObject* Parent) { _X = X; _Y = Y; _Width = Width; _Height = Height; _Parent = Parent; }
CInterfaceComponent::CInterfaceComponent(float X, float Y, float Width, float Height, anchor ChildAnchor, anchor ParentAnchor, CInterfaceObject *Parent, CInterfaceAction *Action) { //... float TX; float TY; switch (ChildAnchor) { case TOPLEFT: TX = X; TY = Y; case TOP: TX = X - (0.5 * Width); TY = Y; case TOPRIGHT: TX = X - Width; TY = Y; case RIGHT: TX = X - Width; TY = Y - (0.5 * Height); case BOTTOM: TX = X - (0.5 * Width); TY = Y - Height; case BOTTOMRIGHT: TX = X - Width; TY = Y - Height; case BOTTOMLEFT: TX = X; TY = Y - Height; case LEFT: TX = X; TY = Y - (0.5 * Height); case CENTER: TX = X - (0.5 * Width); TY = Y - (0.5 * Height); }; switch (ParentAnchor) { case TOP: TX = TX + (0.5 * Parent->GetWidth()); case TOPRIGHT: TX = TX + Parent->GetWidth(); case RIGHT: TX = TX + Parent->GetWidth(); TY = TY + (0.5 * Parent->GetHeight()); case BOTTOMRIGHT: TX = TX + Parent->GetWidth(); TY = TY + Parent->GetHeight(); case BOTTOM: TX = TX + (0.5 * Parent->GetWidth()); TY = TY + Parent->GetHeight(); case BOTTOMLEFT: TY = TY + Parent->GetHeight(); case LEFT: TY = TY + (0.5 * Parent->GetHeight()); case CENTER: TX = TX + (0.5 * Parent->GetWidth()); TY = TY + (0.5 * Parent->GetHeight()); }; // --- X --- }
Wie man sieht verwendet InterfaceObject Absolute Bildkoordinaten wohingegen InterfaceComponent Koordinaten in Bezug zum ParentObject verwendet.
Nun würde ich ganz gerne an der Stelle --- X --- den Konstruktor vom InterfaceObject aufrufen mit den neuen Argumenten TX und TY(anstelle von X, Y). Nur egal wie ich es versuche er sagt mir immer das ich keine Instanz einer Abstrakten Klasse erstellen kann(was ja logisch ist) nur möchte ich keine neue Instanz erstellen sondern einfach den bereits vorhandenen Konstruktor der Vorfahrenklasse verwenden. (Ich habe bereits gesehen dass man das machen kann wenn die Argumente nicht verändert werden, aber ist es nicht möglich wenn ich die Arguemente verändere?)
btw: Komme von Delphi, da ist der Zugriff auf die implementierten Methoden/Konstruktoren einer Abstrakten Vorfahrenklasse ohne Probleme möglich.
-
Du musst eine Initialisierungsliste benutzen. Und den Destruktor solltest du auch virtual machen.
class foo{ int i; public: foo (int _i):i(_i){} virtual ~foo (){} }; class bar : public foo{ public: bar (int z): foo (z) {} ~bar (){} };
-
drakon schrieb:
Du musst eine Initialisierungsliste benutzen. Und den Destruktor solltest du auch virtual machen.
class foo{ int i; public: foo (int _i):i(_i){} virtual ~foo (){} }; class bar : public foo{ public: bar (int z): foo (z) {} ~bar (){} };
Aber dann wird doch beim Aufruf vom foo Konstruktor in bar ein unverändertes X und Y verwendet oder
?
-
FunMaker schrieb:
Aber dann wird doch beim Aufruf vom foo Konstruktor in bar ein unverändertes X und Y verwendet oder
?
Welches X? Welches Y?
EDIT:
Achso, da haben sich das foobar Beispiel und Deins etwas vermischt.Das kannst Du so nicht erreichen. Du kannst den Konstruktor der Basisklasse nur von der Initialisierungsliste aus aufrufen. Alles andere erzeugt ein temporäres Objekt und verwirft dieses gleich wieder.
Potentiell möglich wäre sowas:
class foo1 /* abstract */ { public: foo1( float X, float Y ); }; class foo2 /* abstract */ { public: foo2( float TX, float TY ); float getX() const; float getY() const; }; class bar : foo2, foo1 { public: bar( float X, float Y, Anchor ca, Anchor pa ) : foo2( calculateTX( X, ca, pa ), calculateTY( Y, ca, pa ) ) , foo1( foo2::getX(), foo2::getY() ) {} static float calculateTX( float X, Anchor ca, Anchor pa ); static float calculateTY( float Y, Anchor ca, Anchor pa ); };
-
FunMaker schrieb:
...
Nun würde ich ganz gerne an der Stelle --- X --- den Konstruktor vom InterfaceObject aufrufen mit den neuen Argumenten TX und TY(anstelle von X, Y). ...Ich vermute, dass das, was DU möchtest so nicht geht. Du möchtest (wie gesagt: Meine Vermutung), dass erst der Konstruktor der abgeleiteten Klasse (der dann Werte setzt) und dann der der Basisklasse aufgerufen wird (der dann die oben gesetzten Werte verwendet).
Das geht nicht.
Ob es da irgendeinen "Trick" mit virtuellen Basisklassen gibt, weiß ich nicht, aber ich habe in Erinnerung, dass IMMER zuerst der Basisklassenteil konstruiert wird (=> der Basisklassen-Ctor aufgerufen) und danach der Teil der abgeleiteten Klasse.
Bei Lords "Trick" musst Du aber bedenken, dass Du auf keinen Member der abgeleiteten Klasse zugreifen kannst (und dafür gibt's wohl auch keinen (portablen) für.@Lord: Bist Du sicher, dass das Argument "Beim Aufruf des BasisklassenCtors ist das Objekt noch kein Derivedobject" nicht auch für static Funktionen gilt ?
(auch wenn ich mir vorstellen könnte, dass das in der Praxis funktioniert)
naja aber für "freie Funktionen" würde es auf jeden Fall klappen....
Schöner Trick.Gruß,
Simon2.
-
Simon2 schrieb:
@Lord: Bist Du sicher, dass das Argument "Beim Aufruf des BasisklassenCtors ist das Objekt noch kein Derivedobject" nicht auch für static Funktionen gilt ?
Man darf statische Funktionen sogar ganz ohne Objekt aufrufen, von daher kann das Argument hier nicht gelten.
Eine andere Frage ist jedoch, ist das Objekt nach Aufruf des foo2-Konstrukors, aber vor Aufruf des foo1-Konstruktors bereits ein foo2-Objekt (um die Memberfunktionen f002::getX und foo2::getY aufzurufen)? Hier bin ich unsicher, es müsste aber eigentlich tatsächlich so sein, da sonst das (in boost enthaltene) base-to-member-Idiom keinen Sinn ergeben würde.
-
@Simon/LordJaxom: Genau das ist was ich versuche zu erreichen. Bleibt mir wenn ich es so beibehalten will nichts anderes übrig als die Initialisierungen die ich im Interfaceobject mache einfach nochmal in der Interfacecomponent hinzuschreiben?
Die Idee mit der Doppelvererbung würde zwar ansich gehen, aber da bin ich mir irgendwie ein bisschen zu unsicher und so wie ich das sehe sind dann die beiden Typen der Oberklassen auch nicht zuweisungskompatibel wie es abgeleitete Klassen wären oder?
-
FunMaker schrieb:
@Simon/LordJaxom: Genau das ist was ich versuche zu erreichen....
Das ist dann eine Variante des "virtuellen Konstruktors" ... und der funktioniert eben (zumindestens in C++) nicht und es ist auch nicht unumstritten, ob das überhaupt eine gute Designidee ist (denn Deine Basisklasse variiert seine Schnittstellenzusagen). Zu "virtueller Konstruktor" gibt's schon Einiges hier im Forum....
Gruß,
Simon2.
-
hmh okay, dann werde ich mich mal umgucken, aber ich habe schon eine Vermutung wie ich das Problem löse, da mir aufgefallen ist, dass ich die Koordinaten die im InterfaceObject vorhanden sind mit etwas Umstrukturierung vielleicht doch in die InterfaceComponent bekomme, somit würde ich das Problem umgehen.
Danke an euch.