webentwicklung-frage-antwort-db.com.de

Konstruktoren erben

Warum macht dieser Code:

class A
{
    public: 
        explicit A(int x) {}
};

class B: public A
{
};

int main(void)
{
    B *b = new B(5);
    delete b;
}

Ergebnis in diesen Fehlern:

 main.cpp: In der Funktion 'int main ()': 
 main.cpp: 13: Fehler: Keine passende Funktion für den Aufruf von 'B :: B (int)' 
 main.cpp: 8: note: Kandidaten sind: B :: B () 
 main.cpp: 8: note: B :: B (const B &) 

Sollte B nicht den Konstruktor von A erben?

(dies benutzt gcc)

195
Sydius

Wenn Ihr Compiler den C++ 11-Standard unterstützt, gibt es eine Konstruktorvererbung mit using (Wortspiel beabsichtigt). Weitere Informationen finden Sie unter Wikipedia C++ 11-Artikel . Du schreibst:

class A
{
    public: 
        explicit A(int x) {}
};

class B: public A
{
     using A::A;
};

Das ist alles oder nichts - Sie können nicht nur einige Konstruktoren erben. Wenn Sie dies schreiben, erben Sie alle von ihnen. Um nur ausgewählte zu erben, müssen Sie die einzelnen Konstruktoren manuell schreiben und den Basiskonstruktor nach Bedarf von ihnen aufrufen.

Historisch gesehen konnten Konstruktoren im C++ 03-Standard nicht vererbt werden. Sie mussten sie einzeln manuell erben, indem Sie die Basisimplementierung selbst aufrufen.

348
Suma

Konstruktoren werden nicht vererbt. Sie werden vom untergeordneten Konstruktor implizit oder explizit aufgerufen.

Der Compiler erstellt einen Standardkonstruktor (einen ohne Argumente) und einen Standardkopiekonstruktor (einen mit einem Argument, das auf denselben Typ verweist). Wenn Sie jedoch einen Konstruktor wollen, der ein int akzeptiert, müssen Sie es explizit definieren.

class A
{
public: 
    explicit A(int x) {}
};

class B: public A
{
public:
    explicit B(int x) : A(x) { }
};

UPDATE : In C++ 11 können Konstruktoren vererbt werden. Siehe Sumas Antwort für Details.

84
Avi

Sie müssen den Konstruktor in B explizit definieren und den Konstruktor für das übergeordnete Element explizit aufrufen.

B(int x) : A(x) { }

oder

B() : A(5) { }
7
grepsedawk

Wie wäre es mit einer Template-Funktion, um alle Konstruktoren zu binden?

template <class... T> Derived(T... t) : Base(t...) {}
4
Pradu

Dies ist direkt aus Bjarne Stroustrup's Seite :

Wenn Sie dies wünschen, können Sie sich dennoch selbst in den Fuß schießen, indem Sie Konstruktoren in einer abgeleiteten Klasse erben, in der Sie neue Elementvariablen definieren, die initialisiert werden müssen:

struct B1 {
    B1(int) { }
};

struct D1 : B1 {
    using B1::B1; // implicitly declares D1(int)
    int x;
};

void test()
{
    D1 d(6);    // Oops: d.x is not initialized
    D1 e;       // error: D1 has no default constructor
}
4
nenchev

Richtiger Code ist

class A
{
    public: 
      explicit A(int x) {}
};

class B: public A
{
      public:

     B(int a):A(a){
          }
};

main()
{
    B *b = new B(5);
     delete b;
}

Fehler ist b/c Klasse B hat keinen Parameterkonstruktor, und zweitens sollte sie einen Basisklasseninitialisierer haben, um den Konstruktor des Basisklassen-Parameterkonstruktors aufzurufen

2
Iqbal Haider