Nicht vorhanden Member der Superklasse aufrufen
-
Hallo,
tut mir Leid, mit fiel kein besserer Titel ein xdIch zeig einfach mal direkt den Beispielcode:
#include <iostream> class Base { public: void foo(Base& other); virtual void bar(Base& other) = 0; virtual int kind() = 0; }; class A : public Base { public: void bar(Base& other); int kind(); int a_int; }; class B : public Base { public: void bar(Base& other); int kind(); int b_int; }; void Base::foo(Base& other) { if (kind() == 0) if (other.kind() == 1) bar(other); else if (other.kind() == 0) bar(other); } int A::kind() {return 0;} void A::bar(Base& other) {std::cout << a_int << " " << other.b_int << std::endl;} int B::kind() {return 1;} void B::bar(Base& other) {std::cout << b_int << " " << other.a_int << std::endl;} int main() { A a; B b; a.foo(b); return 0; }Wie man sieht, kann A::bar nur aufgerufen werden, wenn der Parameter ein B-Objekt ist und andersherum.
Theoretisch kann ich also sicher in A::bar auf other.b_int und in B::bar auf other.a_int zugreifen. Aber natürlich weiß der Compiler das ja nicht
Gibts da eine Möglichkeit, wie ich das so machen kann?
-
und wieso genau machst du aus dem int nicht ein Member von Base?
oder eine Virtuelle Get-Methode? zB Base::GetInt()Edit: du kannst natürlich auch dynamic_cast<> oder static_cast<> einsetzen.
Ich empfehle dir aber, wenn du schon polymorphie einsetzt, deine Interface-Klasse so zu planen, dass du keine cast's eisnetzen musst.
-
Eine Wurst schrieb:
Theoretisch kann ich also sicher in A::bar auf other.b_int und in B::bar auf other.a_int zugreifen.
Wenn du absolut sicher bist, dann nimm einen
static_cast.Eine Wurst schrieb:
Theoretisch ...
Die Theorie sieht anders aus. Öffentliche Member können leicht modifiziert werden, wobei du die vermutlich nicht absichtlich öffentlich gemacht hast.
Aber gegen das kannst du dich nicht wehren:
class C : public Base { public: int kind() { return 0; } char *this_is_not_an_integer; };Der einige Ausweg:
dynamic_cast. Vollkommen ungefährlich, vollkommen inperformant und ein guter Indikator für schlechten Code.Egal was du erreichen willst, vergiss es und mach das über eine virtuelle Funktion.
-
Kurz und knapp, dass geht so nicht. Ein A ist ein A und ein B ist ein B, auch wenn Base der Papa von A und B ist. Und Base wird auch niemals die Eigenschaften seiner Kinder kennen. Diese kennen aber die Eigenschaften, die sie von Base geerbt haben. Du solltest dir die Polymorphie noch mal ansehen, so macht das alles keinen Sinn. Polymorphie ist auch nur mit Zeigern möglich. Was damit zusammen hängt, dass A eben kein Base ist, aber A ein Base enthält.
-
Paul Müller schrieb:
[...] Polymorphie ist auch nur mit Zeigern möglich. Was damit zusammen hängt, dass A eben kein Base ist, aber A ein Base enthält.
Referenzen sind schon okay. Es müssen keine Zeiger sein.
-
und wieso genau machst du aus dem int nicht ein Member von Base?
oder eine Virtuelle Get-Methode? zB Base::GetInt()Weil nur manche Subklassen von Base diesen Member haben.
Aber gegen das kannst du dich nicht wehren:
Du meinst, dass man auch eine Klasse schreiben kann, die kind() -> 0 liefert und nicht in das Muster passt?
Das werde ich nicht tun und da das Projekt keine öffentliche Lib o.ä. wird, wird das wohl auch kein anderer
Also gibt es außer static_cast keine Lösung?
Dann werd ich den wohl benutzen oder mir was anderes einfallen lassen müssen
-
Paul Müller schrieb:
Kurz und knapp, dass geht so nicht.
Mit einem Cast geht dass sehr wohl.
Paul Müller schrieb:
Diese kennen aber die Eigenschaften, die sie von Base geerbt haben.
Aber nicht alle...
Paul Müller schrieb:
Polymorphie ist auch nur mit Zeigern möglich.
Kennst du die STL? Solange die abgeleiteten Klassen nicht zusätzlichen Speicher benötigen, und durch pImpl ist das geht überall, sind nicht einmal Referenzen notwendig.
Paul Müller schrieb:
[...] dass geht so nicht [...] auch [...] auch [...] macht Sinn [...] auch [...]
Dein schönes Deutsch macht auch viel Sinn.
-
Wurst schrieb:
Also gibt es außer static_cast keine Lösung?
Dann werd ich den wohl benutzen oder mir was anderes einfallen lassen müssen
Die Lösungen wurden schon genannt (je weiter oben, desto besser):
- Überdenken des Designs. Das Problem kommt mir sinnlos vor.
- Zusätzliche virtuelle Funktion
- Cast: static_cast oder dynamic_cast
Wurst schrieb:
Das werde ich nicht tun und da das Projekt keine öffentliche Lib o.ä. wird, wird das wohl auch kein anderer
Aber lass dir gesagt sein: davon sollte man immer ausgehen.
-
Zusätzliche virtuelle Funktion
Ich sag ja, das würde nicht so funktionieren, weil ein Teil der Subklassen von Base diesen Member nicht hat.
-
wurst schrieb:
Zusätzliche virtuelle Funktion
Ich sag ja, das würde nicht so funktionieren, weil ein Teil der Subklassen von Base diesen Member nicht hat.
Die brauchen ihn ja auch nicht zu haben. Die geben da einfach 0 oder sowas zurück.
-
Ich sag ja, das würde nicht so funktionieren, weil ein Teil der Subklassen von Base diesen Member nicht hat.
Zwischenklasse, die von Base erbt, diesen Member deklariert und von der dieser Teil der Subklassen erbt. Als Parameter-Typ nimmst du dann die Zwischenklasse.