Mehrfachvererbung und VCL
-
Hallo!
Ich verwende den BCB4 und möchte eine Komponente schreiben, die aus der VCL erbt. Da ich damit etwas visualisieren möchte will ich auch noch von einer Subscriber-Klasse erben:
class Screen { public: class Subscriber { virtual void Notify(int x, int y) = 0; } } class TScreenView : public Graphics::TImage, Screen::Subsriber // hier motzt er { }
Jetzt meckert der BCB aber, Komponenten dürften nicht mehrfach erben.
Das man nicht von 2 Komponenten erben darf ist logisch, wegen der doppelten Basisklassenanteile, aber warum darf ich nicht von einer selbst geschrieben Klasse (in der Tat sogar nur ein Interface mit einer einzigen virtuellen Methode) erben?
Gibt es eine Möglichkeit das trotzdem hinzukriegen oder muß ich mir was anderes einfallen lassen?Danke für Eure Hilfe
Jester
-
warum nicht so:
class Screen { public: class Subscriber : public Graphics::TImage { virtual void Notify(int x, int y) = 0; ... } } class TScreenView : Screen::Subsriber // hier motzt er nicht { }
-
Jo, das würde wohl funktionieren. Allerdings ist mir das nicht so recht, weil dadurch jede Klasse, die sich registrieren will einen TImage-Anteil bekommt. Das ist nicht sehr praktisch und es kann gut sein, daß ich noch mehr Objekte einhängen will.
Aber trotzdem Danke.
Wenn es garnichts anderes gibt kann ich es ja immer noch damit versuchen.MfG Jester
-
@Xqgene: Deine Lösung ist nicht mehr das, was hier vorliegt. Subscriber ist ein Interface und kein TImage.
@Jester: wo hast Du denn diese Lösung gesehen?
Btw, Volkard war sowieso dagegen daß die komplette Klasse vom Subscriber erbt, darüber hatten wir in der späten Nacht noch diskutiert.
Entkoppeln über zusätzliche Klasse...
class Screen { public: class Subscriber { virtual void Notify(int x, int y) = 0; } } // hier wolltest Du ja sowas machen: class TScreenView : public Graphics::TImage, Screen::Subsriber // hier motzt er { virtual void Notify(int x, int y) { doDraw(x,y); } } // Lösungsvorschlag: class TScreenView : public Graphics::TImage { class DodrawSubscriber : public Subscriber { public: DodrawSubscriber(TScreenView* pView) : m_pView(pView) {} virtual void Notify(int x, int y) { m_pView->doDraw(x,y) } private: TScreenView* m_pView; }; DodrawSubscriber m_dodrawSubscriber; public: TScreenView() : m_dodrawSubscriber(this) {...} };
Das ist der ursprüngliche Gedanke... nur sind hier die Klassen nicht mehr direkt gekoppelt, sondern über ein Bindeglied.
-
@Marcus: Ja, die Lösung ist gut, was?
Sowas mit ner Zusatzklasse hatte ich mir auch schon überlegt, hielt es aber eigentlich mehr für ein Workaround. Welche Gründe sprechen denn dagegen vom Subscriber direkt zu erben?
btw:
m_pView->doDraw(x,y)
Wir haben aber ein fleißiges Syntaxcoloring, das macht sogar Überstunden (doDraw)
-
Das do habe ich schon gesehen.
Tja, warum nicht? Weil häufig ja nicht das ganze Objekt ein Subscriber ist, sondern eigentlich nur eine Methode davon. Stell Dir vor, Du willst zwei Subscriber einhängen, also in Abhängigkeit von zwei Ereignissen unterschiedliche Methoden aufrufen, aber im gleichen View. Dann hast Du ein Problem, weil die direkte Vererbung nur einen Slot hergibt, Du aber vielleicht mehr Slots benötigst.
Naja, abgesehen von der theoretischen Überlegung löst es hier auch gleich Dein Problem mit der Mehrfachvererbung. Es ist immer unschön, wenn man Frameworken-Klassen noch Dinge aufzwingt, die sie eigentlich nicht wollen sollen - selbst wenn es erlaubt wäre.
-
Jester schrieb:
Jetzt meckert der BCB aber, Komponenten dürften nicht mehrfach erben.
Das man nicht von 2 Komponenten erben darf ist logisch, wegen der doppelten Basisklassenanteile, aber warum darf ich nicht von einer selbst geschrieben Klasse (in der Tat sogar nur ein Interface mit einer einzigen virtuellen Methode) erben?Die doppelten Basisklassen könnte man mit virtueller Vererbung umgehen, oder? Der Grund wieso das aber nicht funktioniert ist, dass VCL in Delphi geschrieben ist, und Delphi unterstützt keine Mehrfachvererbung, außer Schnittstellenvererbung. Für Schnittstellen hat Delphi im Gegensatz zu C++ ein eigenes Schlüsselwort (interface). Und in C++ ist eine Schnittstelle auch eine Klasse. Deswegen funktioniert es nicht.
PS: Ich könnte mit der Aussage auch ganz daneben liegen. Es ist nur meine Vermutung
-
Das mit der virtuellen Basis ist richtig, allerdings müßten dann schon die Komponenten aus der VCL virtuell geerbt haben, und das haben sie nunmal nicht. Das wäre auch recht unangenehm, da man virtuelle Basisklassen immer direkt initialisieren muß.
Ärgerlich ist halt, daß ich auch keine ungefährliche Klasse mit reinerben darf. Aber die jetzige Lösung ist ja mindestens genausogut und vielleicht sogar besser.MfG Jester
-
hm,
class Screen { public: class Subscriber { virtual void Notify(int x, int y) = 0; } ; }; class TScreenView : public TImage , Screen::Subscriber// hier motzt er nicht ! { virtual void Notify(int x, int y) { doDraw(x,y); } void doDraw(int X,int Y){}; };
macht er einwandfrei....
zumindest mit dem BCB6 Enterprise, der mit Mehrfachvererbung schon recht gut zurecht kommt