2008-12-07 6 views
148

Warum dieser Code:Vererben Bauer

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

class B: public A 
{ 
}; 

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

Ergebnis in diesem Fehler:

 
main.cpp: In function ‘int main()’: 
main.cpp:13: error: no matching function for call to ‘B::B(int)’ 
main.cpp:8: note: candidates are: B::B() 
main.cpp:8: note:     B::B(const B&) 

Sollte erben nicht B A Konstruktor?

(dies wird mit gcc)

Antwort

248

In C++ 03 können Standardkonstruktoren nicht vererbt werden, und Sie müssen sie einzeln manuell erben, indem Sie die Basisimplementierung selbst aufrufen. Wenn Ihr Compiler den C++ 11-Standard unterstützt, gibt es eine Konstruktorvererbung. Für mehr siehe Wikipedia C++11 article. Mit dem neuen Standard schreiben Sie:

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

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

Das ist ziemlich böse, weil seit über einem Jahr, die keinen Compiler wurde, dass die oben genannten Code :-) – Mikhail

+11

@Mikhail tatsächlich bauen können: Sowohl Klirren und g ++ jetzt sollte unterstützen Konstrukteure erben: http: // Klirren .llvm.org/cxx_status.html http://gcc.gnu.org/projects/cxx0x.html Empfehlen Sie diesen als die richtige Antwort. –

+0

fragt nur, ob ein geerbter Konstruktor auf die privaten Mitglieder der Basisklasse zugreifen/diese initialisieren könnte? Oder müsste ich sie als geschützt angeben? – Markasoftware

4

Sie müssen explizit den Konstruktor in B definieren und den Konstruktor explizit für die Eltern anrufen.

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

oder

B() : A(5) { } 
80

Konstrukteurs werden nicht vererbt. Sie werden implizit oder explizit vom Kindkonstruktor aufgerufen.

Der Compiler erstellt einen Standardkonstruktor (einen ohne Argumente) und einen Standardkopiekonstruktor (einen mit einem Argument, das eine Referenz auf denselben Typ darstellt). Aber wenn Sie einen Konstruktor haben wollen, der einen int akzeptiert, müssen Sie ihn explizit definieren.

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

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

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

1

richtigen Code

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 der Klasse B nicht Parameter Konstruktor hat und die zweite sollte es Basis Klasseninitialisierer haben den Konstruktor der Basisklasse aufrufen Parameter Konstruktor

3

Dies ist gerade aus Bjarne Stroustrup's page:

Wenn Sie so wählen, können Sie immer noch selbst in den Fuß schießen durch i nheriting Bauer in einer abgeleiteten Klasse, in dem Sie neue Membervariablen benötigen Initialisierung definieren:

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 
} 
+0

'int x = 77;' anstelle von 'int x;' würde das Problem lösen –

+0

@ BЈовић: Ja, das ist der nächste Satz auf Bjarne Seite :) –

1

Wie über eine Template-Funktion mit allen Konstrukteuren zu binden?

template <class... T> Derived(T... t) : Base(t...) {} 
+2

Wahrscheinlich sollten Sie es mit perfektem Forwarding tun: template B (args && ... args) : A (std :: forward < Args > (args) ...) {} –

+0

Und Sie haben gerade 'Derived' Kopie Konstruktor gebrochen. – Barry

+0

Müsste der Konstruktor von Base auch templatiert werden? Wenn du Base (t ...) nennst, müsste Base für das Template templated sein? – Zebrafish