Vererbung funktioniert nicht?!



  • Hallo,

    ich war gerade ganz verduzt, als folgendes nicht funktioniert hat:

    class A
    {
       void func( A** ppA );
    };
    
    class B : public A
    {   
    };
    
    B* globalB;
    
    int main()
    {
       B localB;
       localB.func( &globalB );
    
    }
    

    Der Compiler meldet hier, dass er B** nicht in A** konvertieren kann.
    Vielleicht ist die Frage ja doof, aber ich hätte eigentlich erwartet dass das gehen müsste da B ja von A erbt.

    Geht das wirklich nicht oder hab ich nur was falsch gemacht?



  • Klassen haben als Default private, deine Methode ist
    also private, und wird somit nicht vererbt.

    Devil



  • 0x00000001 schrieb:

    Der Compiler meldet hier, dass er B** nicht in A** konvertieren kann.
    Vielleicht ist die Frage ja doof, aber ich hätte eigentlich erwartet dass das gehen müsste da B ja von A erbt.

    Das eine hat mit dem anderen nichts zu tun. B erbt von A und deshalb ist B implizit nach A konvertierbar. Gleichzeitig ist auch B* in A* konvertierbar. B** und A** stehen aber in keinerlei Beziehung.

    Eine implizite Konvertierung von B** nach A** würde ein Loch in das C++ Typsystem reißen.
    Schau mal:

    B b;            // wir starten mit einem B...
    B* pB = &b;     // und einem Zeiger auf dieses B
    A** ppa = &pB;  // Wir konvertieren diesen nach A** (das geht zum Glück nicht!)
    C* c;           // Und definieren einen Zeiger auf C (C erbt von A)
    A** ppa2 = &c;  // Und konvertieren diesen nach A** (das geht zum Glück nicht!)
    *ppa2 = *ppa1;  // Ups! Und aufeinmal zeigt ein C* auf ein B obwohl C und B nicht kompatibel sind!
    


  • devil81 schrieb:

    Klassen haben als Default private, deine Methode ist
    also private, und wird somit nicht vererbt.

    Was allerdings nichts mit der Konvertierung zwischen A** und B** zu tun hat.



  • Vielen Dank für die Erklärung.

    Wie kann ich das lösen? Ich möchte einen Zeiger übergeben, und der Wert des Zeigers kann sich in der Funktion ggf. ändern. Also brauche ich einen Zeiger auf einen Zeiger.
    Kann man das irgendwie hinkriegen, ohne dass man bei jedem Funktionsaufruf entsprechend castet um den Compiler ruhig zu stimmen?



  • 0x00000001 schrieb:

    Wie kann ich das lösen? Ich möchte einen Zeiger übergeben, und der Wert des Zeigers kann sich in der Funktion ggf. ändern. Also brauche ich einen Zeiger auf einen Zeiger. Kann man das irgendwie hinkriegen

    Nimm doch einfach eine Referenz auf einen Zeiger.

    void func(A*& a)
    {
       a = new B();
    }
    void gunc()
    {
        A* a = 0;
        func(a);
        assert(a != 0);
    }
    

    ohne dass man bei jedem Funktionsaufruf entsprechend castet um den Compiler ruhig zu stimmen?

    Das wäre die denkbar schlechteste Lösung.



  • Ich weiß nicht warum, aber das mit den Referenzen geht leider nicht.
    Die Funktion selbst wird kompiliert, bei dem Aufruf gibt es aber wieder die Meldung "B* nicht konvertierbar nach A*&".
    Ich habe es so gemacht wie in deinem kleinen Codebeispiel.

    Sollte das letztendlich nicht gehen werde ich einfach den neuen Wert des Zeigers zurückgeben und ihn ausßerhalb der Funktion umschreiben. Sieht hässlich aus, aber was will man machen 🙄



  • 0x00000001 schrieb:

    Die Funktion selbst wird kompiliert, bei dem Aufruf gibt es aber wieder die Meldung "B* nicht konvertierbar nach A*&".

    Jo. Das ist natürlich richtig und hatte ich jetzt gar nicht bedacht.

    Mir fallen spontan zwei saubere Lösungen ein:

    #include <cassert>
    class A {};
    class B : public A {};
    template <class T>
    void func(T*& p)
    {
    ...
    }
    
    void gunc() 
    { 
        A* a = 0; 
        B* b = 0;
        func(a); 
        func(b);
        assert(a != 0); 
        assert(b != 0); 
    }
    

    Oder halt ein guter alter Rückgabewert:

    A* func(A* a) {...}
    
    void gunc()
    {
       A* a = 0;
       B* b = 0;
       a = func(a);
       b = func(b);
    }
    

    Wobei ich wohl die zweite Lösung vorziehen würde.
    Das macht die Aktion viel deutlicher und verschleiert das ganze nicht hinter einem Ein-/Ausgabe-Parameter.



  • Ja ich denke ich werde es jetzt mit einer Rückgabe machen.

    Vielen Dank nochmal für Deine ausführlichen Antworten.


Anmelden zum Antworten