Vererbungsproblem
-
So siehts derzeit aus:
+---------+ | A | +---------+ ^ | +----------+----------+ | | +---------+ +---------+ | B | | C | +---------+ +---------+ ^ ^ | +---------+ | | | D | | | +---------+ | | ^ | | +-------+-------+ | | | | | +---------+ +---------+ | BImpl | | CImpl | +---------+ +---------+Also
BundCsind vonAabgeleitet, die beide inBImplbzw inCImplspezialisiert sind.BundCsind generierte Klassen, daran kann ich nichts ändern.
Jetzt brauche ich eine gemeinsame BasisklasseD, die ich statt einer spezialisierten Klasse verwenden will (zwecks Polymorphie).
Das Problem ist, ich hab jetzt zwar eine Variable vom TypD(die entweder einBImpl- oderCImpl-Objekt enthält), andere Methoden erfordern aber ein Objekt vom TypA. Und davon kann ich ja in meiner Basisklasse nicht ableiten, weil der Compiler dann logischerweise eine mehrdeutige Ableitung entdeckt...Ich hoffe, der Text war halbwegs verständlich
Kurz: Ich hab eine Variable vom Typ
D, brauch aber eine Variable vom TypA
-
Schon dynamic_cast probiert?
D* foo = new BImpl(); A* bar = dynamic_cast<A*>(foo);
-
So wie es das Bild zeigt geht das nicht. D und A haben nichts miteinander zu tun. Folglich kann ein D auch kein A sein.
-
@C Newbie: genau das wollte ich eigentlich vermeiden
@Tachyon: schön, dass du wiederholst, was ich bereits weiß. Wenn es gehen würde, würde ich auch nicht nach einer Alternativlösung fragen

-
zwutz schrieb:
@C Newbie: genau das wollte ich eigentlich vermeiden
@Tachyon: schön, dass du wiederholst, was ich bereits weiß. Wenn es gehen würde, würde ich auch nicht nach einer Alternativlösung fragen

Gefragt hast Du gar nichts. Und dass Du weißt, dass man D nicht in A überführen kann, hast Du auch nicht geschrieben. Der dynamic_cast ist hier tatsächlich zu vermeiden, weil er falsch ist.
Wenn B und C generiert sind, ist dann auch A generiert?
Ansonsten: Mache es wie gezeigt, nur dass BImpl und CImpl D als Aggregat benutzen und nicht davon erben.
-
Tachyon schrieb:
Ansonsten: Mache es wie gezeigt, nur dass BImpl und CImpl D als Aggregat benutzen und nicht davon erben.
damit kann ich was anfangen, danke
-
Tachyon schrieb:
zwutz schrieb:
@C Newbie: genau das wollte ich eigentlich vermeiden
@Tachyon: schön, dass du wiederholst, was ich bereits weiß. Wenn es gehen würde, würde ich auch nicht nach einer Alternativlösung fragen

Gefragt hast Du gar nichts. Und dass Du weißt, dass man D nicht in A überführen kann, hast Du auch nicht geschrieben. Der dynamic_cast ist hier tatsächlich zu vermeiden, weil er falsch ist.
Warum ist der dynamic_cast falsch?
Natürlich D und A haben direkt nichts miteinander zu tun. Aber wenn z.B. ein BImpl hinter dem Zeiger steckt kann ich einen Downcast von D* nach BImpl* machen und dann habe ich mein A. Darum habe ich gedacht der dynamic_cast ist ok.
Ich habe es auch gerade kurz getestet und in dem Minimalbeispiel ging es (Was aber nichts heißen muss).
Also was habe ich dabei übersehen?
-
C Newbie schrieb:
Also was habe ich dabei übersehen?
Ja, laut C++-Standard ist das "ill-formed". Es produziert also UB.
-
hm... scheint doch nicht so zu gehen, wie ich es mir vorgestellt habe.
Folgendes: Ich habe einen Eingabedialog mit diversen Eingabefeldern. Die meisten davon sind variabel, also abhängig von der Umgebung sollen mal die einen, mal die anderen geladen werden.
Also habe ich diese Teile in extra Dialoge ausgelagert, die dann einfach zur Laufzeit in einen Platzhalter geladen werden. Diese zwei Teile sind in meinem Beispiel BImpl und CImpl. A ist eine Basisklasse aus dem Framework und B und C sind generiert und enthalten dem vom GUI-Designer erstellten Code.Jetzt sollen natürlich beide Teildialoge eine saveData- und eine loadData-Methode haben. Da erst zur Laufzeit entschieden wird, welcher Dialog genau angezeigt wird, wollte ich diese Methoden in einer Klasse (D) als pure virtual definieren und in jedem Dialog entsprechend ausprogrammieren.
in etwa so würde es im Code aussehen:class MeineKlasse { ... private: D* _dialog; }; MeineKlasse::MeineKlasse() { if (foo) _dialog = new BImpl(); else _dialog = new CImpl(); }im weiteren Code wollte ich nur mit _dialog arbeiten. Rein theoretisch geht das auch, nur müsste _dialog für andere Methoden von A abgeleitet sein, was leider nicht geht (siehe mein Schaubild oben)
Aber ich befürchte, über Vererbung ist das nicht lösbar...
-
Das Problem ist, ich hab jetzt zwar eine Variable vom Typ D (die entweder ein BImpl- oder CImpl-Objekt enthält),
Verstehe ich nicht. Wer enthält wen? Meinst Du, dass Du einen Zeiger oder eine Referenz auf ein D Objekt hast, was ein Subobjekt eines BImpl- oder CImpl-Objekts ist?
Wenn Du an A,B,C nichts ändern kannst, könntest Du in D eine pure virtuelle Funktion hinzufügen, die einem den Zugriff auf das A-Subobjekt erlaubt, nicht?
class D { ... virtual A& accessA() = 0; ... };Ansonsten könnten B, C und D virtuell von A erben. Aber das geht natürlich nicht, wenn Du B und C nicht ändern darfst.