Anfängerfrage zu Inheritance



  • Ich habe folgenden Code:

    class Base
    {
    public:
        void doSomething() {}
    };
    
    class Derived : public Base
    {
    public:
        void doSomethingElse() {}
    
    };
    
    class X
    {
    public:
        Base createBase()
        {
            Base b;
            return b;
        }
    };
    
    int main
    {
        X x;
        Derived d = x.createBase();
        //hier kommts zum Fehler: 
        //no suitable user-defined conversion from "Base" to "Derived" exists
    }
    

    Beim Kompilieren in VS 2015 bekomme ich folgended Fehlermeldung:
    no suitable user-defined conversion from "Base" to "Derived" exists"
    Wieso? Ich dachte, C++ macht automatisches Upcasting?

    Was muss ich machen, damit der Fehler nicht mehr auftritt?
    Einen extra Konstruktor in Derived?
    (Die Klasse X kann ich nicht ändern, weil sei in meinem Fall von einem Framework bereitgestellt wird)


  • Mod

    In Worten ausgedrückt hast du "Ein Derived ist ein Base" programmiert. Jetzt willst du aber ein Base in ein Derived behandeln. Das ist wie zu sagen "Ein Hund ist ein Tier" und dann ein (beliebiges) Tier wie einen Hund zu behandeln. Geht im allgemeinen schief.

    Alatar schrieb:

    Was muss ich machen, damit der Fehler nicht mehr auftritt?

    Das kommt drauf an, was du damit erreichen möchtest. Ich sage nicht, dass es unvorstellbar ist, dass diese Operation Sinn machen könnte, aber im Moment sieht es eher so aus, als hättest du nicht wirklich verstanden, welche Beziehungen zwischen Klassen mittels Vererbung ausgedrückt werden.



  • Danke für die Antwort.

    Ich habe festgestellt, dass sich das Ganze kompilieren lässt, wenn ich einen Konstruktor in Derived hinzufüge, der ein Base Objekt nimmt. Die Derived Klasse sieht damit so aus:

    class Derived : public Base
    {
    public:
        Derived(Base& b)
            :Base()
        {
        }
    
        void doSomethingElse() {}
    
    };
    

    Aber jetzt habe ich ein anderes Problem. Beim Kompilieren kommt die Warnung:
    1> warning C4239: nonstandard extension used: 'argument': conversion from 'Base' to 'Base &'
    1> note: A non-const reference may only be bound to an lvalue

    Ich kann die Warnung wegbekommen, indem ich die Referenz im Konstruktor durch ein "Valueobjekt" ersetze also so:

    class Derived : public Base
    {
    public:
        Derived(Base b)
            :Base()
        {
        }
    
        void doSomethingElse() {}
    
    };
    

    Aber das will ich lieber nicht, weil dann Base jedes Mal kopiert wird, was unnötig ist und extra Speicher und Zeit braucht.

    PS: Vielleicht sollte ich für diese Warnung einen neuen Thread aufmachen... 🙂



  • Was möchtest du durch diese Konstruktion erreichen? So wie du es jetzt hast erstelllst du ein neues Derived Objekt indem du einen Konstruktor erstellt hast der Base Objekte nimmt. Allerdings machst du mit diesem Base Objekt überhaupt gar nichts. Du hättest auch Derived d; schreiben können und hättest das gleiche Objekt.

    Zu der Referenz Problematik: const Referenzen können auch rvalues binden.



  • Alatar schrieb:

    Ich habe festgestellt, dass sich das Ganze kompilieren lässt

    Es gibt viele Methoden, solange auf den Compiler einzuprügeln, bis der aufgibt und sich sagt: wenn er meint. Dabei kommt aber selten etwas sinnvolles heraus.

    Du kannst aus einem Base kein Derived machen! Bestenfalls kannst du Werte aus einem Base in ein neues Derived kopieren.



  • sebi707 schrieb:

    Zu der Referenz Problematik: const Referenzen können auch rvalues binden.

    Danke für den Hinweis. Mit "const" klappt es jetzt.
    Habe in der Derivedklasse einen Konstruktor erstellt, der ein "const Base&" Objekt nimmt. Das funktioniert.



  • Alatar schrieb:

    sebi707 schrieb:

    Zu der Referenz Problematik: const Referenzen können auch rvalues binden.

    Danke für den Hinweis. Mit "const" klappt es jetzt.
    Habe in der Derivedklasse einen Konstruktor erstellt, der ein "const Base&" Objekt nimmt. Das funktioniert.

    Bis Base und Derived Membervariablen haben ...


Log in to reply