Virtuelle Vererbung und non-triviale Konstruktoren



  • Ich bin gerade auf folgendes gestoßen:

    struct A
    {
    	A(int, int) { }
    };
    
    struct A1 :
    	virtual A
    {
    	A1(int a, int b) : A(a,b) { }
    };
    
    //ignore
    struct A2 :
    	virtual A
    {
    	A2(int a, int b) : A(a,b) { }
    };
    
    struct B : A1
    {
    	B(int a, int b) : A1(a,b) /*, A(a,b) */ { }
    };
    

    Der oben gepostete Code lässt sich mit VC7.1 gar nicht kompilieren, mit der Fehlermeldung, A habe keinen default-ctor, was ja klar ist. Fügt man jedoch in die Basis-Initialisierungsliste A(a,b) ein, oder leitet A1 von A ganz normal ab, gibt es keine Fehlermeldungen mehr.

    Warum müssen also bei virtual inheritance alle Basis-Klassen mit non-trivialen Konstruktoren, in den Initialisierungslisten der abgeleiteten Klassen eingetragen sein? Oder ist es doch falsch?

    Vielleicht kann jemand die genaue Stelle aus dem Standard zitieren, denn ich konnte zum Thema leider nichts finden.



  • struct A
    {
        A(int, int) { }
    };
    
    struct A1 : A
    {
        A1() : A(1,2) { }
    };
    
    struct A2 : A
    {
        A2() : A(2,3) { }
    };
    
    struct B : A1, A2
    {
        B() { }
    };
    

    alles klar, B hat zwei A. kompliziert (hat MI so an sich), aber OK.
    und jetzt:

    struct A
    {
        A(int, int) { }
    };
    
    struct A1 :
        virtual A
    {
        A1() : A(1,2) { }
    };
    
    struct A2 :
        virtual A
    {
        A2() : A(2,3) { }
    };
    
    struct B : A1,A2
    {
        B() {}
    };
    

    ups, wie soll denn A initialisiert werden?
    das ist das problem, 12.6.2/6 ist die lösung im standard dazu.

    Shlo schrieb:

    Der oben gepostete Code lässt sich mit VC7.1 gar nicht kompilieren, mit der Fehlermeldung, A habe keinen default-ctor, was ja klar ist. Fügt man jedoch in die Basis-Initialisierungsliste A(a,b) ein, oder leitet A1 von A ganz normal ab, gibt es keine Fehlermeldungen mehr.

    C++ Standard schrieb:

    All sub-objects representing virtual base classes are initialized by the constructor of the most derived class (1.8). If the constructor of the most derived class does not specify a mem-initializer for a virtual base class V, then V's default constructor is called to initialize the virtual base class subobject.

    gefährlich! aber es geht weiter:

    If V does not have an accessible default constructor, the initialization is ill-formed. A mem-initializer naming a virtual base class shall be ignored during execution of the constructor of any class that is not the most derived class.

    das erklärt dein beispiel, also gerade noch glück gehabt.


Log in to reply