Basisklassenfunktion von abgeleiteter Klasse aus aufrufen



  • Hallo

    lumpinus schrieb:

    Woher kennt B A ?

    B wird doch von A abgeleitet und daher kennt es auch die Funktionen von A.

    chrische



  • In Tutorials und Büchern steht, dass B::Load() A::Load() überschreibt und A::Load() damit für B gestorben ist. Der this Zeiger zeigt ja auf B nur welcher Zeiger zeigt auf A? Keiner, denn es gibt ja keine Instanz von A.



  • Der this Zeiger zeigt auf A. Denn ein B ist ein A. Ist das wirklich so schwer zu kappieren?



  • Doch: die Klasse B ist ja von A abgeleitet, deshalb gibt es irgendwo in ihrem Inneren noch einen A-Anteil - und dessen Elemente kannst du erreichen, indem du das A:: verwendest (auch wenn B sie überschrieben hat).



  • Ok, this zeigt auf A.
    ist mit this->Load() dann A oder B gemeint??

    Doch wohl B, sonst wäre das doch total sinnlos!!!



  • Ok,
    anscheinend komm ich nicht dahinter. Dann schreib ich jetzt eben statt A::Load A::LoadBasis.



  • lumpinus schrieb:

    Ok,
    anscheinend komm ich nicht dahinter. Dann schreib ich jetzt eben statt A::Load A::LoadBasis.

    Dein Load aus B überdeckt lediglich die Sichtbarkeit von dem Load aus A.
    Wenn du aber explizit angibst dass Load aus A benutzt werden soll wird auch diese Version genommen.
    Nichts anderes macht A::Load.
    Also was soll der Bullshit mit LoadBasis??
    Nur weil du es noch nicht verstanden hast?
    Es funktioniert doch mit A::Load,oder etwa nicht?Oder hast du es nach etwa 30 Posts noch nichtmal versucht?

    Gruß Spacelord



  • Hallo,

    du solltest dringend noch mal das Kapitel über Klassen und Vererbung lesen. Auch das Thema Sichtbarkeit von Namen solltest du dir nochmal anschauen.

    Mal ganz grob und kurz:

    Vererbung ist in der OOP eine "ist-ein"-Beziehung. D.h. ein Objekt einer abgeleiteten Klasse ist immer auch ein Objekt der Basisklasse. In C++ wird dies durch eine "Composition by value" erreicht. D.h. eine abgeleitete Klasse enthält immer auch alle Elemente seiner Basisklassen.

    Wenn du also eine Klasse B von einer Klasse A ableitest, dann sieht ein B-Objekt nachher (konzeptionell) so aus:

    |---------|
    | |-----| |
    | |  A  | |
    | |-----| |
    |    B    |
    |---------|
    

    In dem B ist als auch ein A-Objekt. Der A-Teil gehört fest zu B und kann in B ohne Probleme referenziert werden. Solange sich die Namen der Elemente von A und B unterscheiden, kannst du sie einfach mit ihrem Namen ansprechen. Sollten A und B allerdings Elemente gleichen Namens besitzen, so musst du sagen, welches Element du meinst. Das geht über den Scope-Resolution-Operator ::.

    struct A {
      int i;
    };
    
    struct B : A {
      int i;
      void f() {
        i = 2;      // i von B
        A::i = 2;   // i aus dem A-Teil von B
      }
    };
    

    Da ein B immer auch ein A ist, kannst du ein B z.B. auch über eine A-Referenz referenzieren:

    struct A {
      int i;
    };
    
    struct B : A {
      int i;
      void f() {
        this->i = 2;    // i von b
        // this ist vom Typ B* und jedes B 
        // ist immer auch ein A.
        // Nach der Zuweisung zeigt self auf den A-Teil von B
        A* self = this; 
        self->i = 2;    // i vom A-Teil von B
      }
    };
    

    Mit den Methoden verhält es sich ähnlich, nur das diese natürlich nicht pro Objekt existieren und mit dem Überladen und dem Überschreiben noch zwei Besonderheiten hinzukommen. Für diesen Thread wichtig: Jede abgeleitete Klasse kann alle (nicht privaten)-Methoden der Basisklasse verwenden. Auch hier gilt: sollte eine Methode der Basisklasse den selben Namen (besser: die selbe Signatur) haben, wie eine Methode der abgeleiteten Klasse, muss man in der abgeleiteten Klasse angeben, welche Methode man meint. Dazu verwendet man wiederum den Scope-Resolution-Operator (bei Namensgleichheit würde man besser auf eine using-Deklaration und damit Überladung vertrauen).

    Z2 schrieb:

    Der this Zeiger zeigt auf A. Denn ein B ist ein A. Ist das wirklich so schwer zu kappieren?

    Das stimmt nicht. Der this-Zeiger in diesem Fall auf das gesamte Objekt (also B). Wo sich der A-Teil in B befindet wird vom Standard nicht festgelegt, insofern ist nicht garantiert, dass die Adressen von B und dem A-Teil von B identisch sind - auch wenn das bei den meisten Compilern bei einfacher Vererbung der Fall sein dürfte.

    Ok, this zeigt auf A. ist mit this->Load() dann A oder B gemeint??

    Ohne die Deklaration von A::Load zu kennen, kann man diese Frage nicht beantworten. Kennst du bereits den Unterschied zwischen virtuellen und nicht-virtuellen Methoden und damit den Unterschied zwischen statischem und dynamischem Typ?



  • @HumeSikkins:
    Ich bin ja ganz begeistert von dem liebevoll arrangierten ASCII-Art Bildchen 😃 😉 .
    Wollen wir mal hoffen dass die gesamte Mühe nicht umsonst war(und irgendwie legen mir die letzten zig Posts dieses nahe).

    Gruß Spacelord



  • Was virtuelle Methoden sind weis ich aber was hat das mit statisch und dynamisch zu tun?



  • statischer Typ: Der Typ, den du im Quelltext angegeben hast
    dynamischer Typ: Der tatsächliche Typ, der sich hinter dem Objekt verbirgt

    (die können sich unterscheiden 😉 Wenn du z.B. "A* ptr = new B;" anlegst, hast du einen statischen A, hinter dem sich dynamisch ein B versteckt)


Anmelden zum Antworten