2008-12-07 4 views
148

Pourquoi ce code:constructeurs Hériter

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

class B: public A 
{ 
}; 

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

Résultat dans ces erreurs:

 
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&) 

devrait pas hériter B constructeur de A?

(ce qui est gcc)

Répondre

248

Dans C++ 03, les constructeurs standard ne peuvent pas être hérités et vous devez les hériter manuellement un par un en appelant vous-même l'implémentation de base. Si votre compilateur prend en charge la norme C++ 11, il existe un héritage de constructeur. Pour plus voir Wikipedia C++11 article. Avec la nouvelle norme, vous écrivez:

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

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

Ceci est tout à fait mal parce que depuis plus d'une année qui n'a pas été compilateur qui peut réellement construire le code ci-dessus :-) – Mikhail

+11

@Mikhail: Les deux clang et g ++ devrait soutenir maintenant héritant des constructeurs: http: // clang .llvm.org/cxx_status.html http://gcc.gnu.org/projects/cxx0x.html Recommandez ceci comme bonne réponse. –

+0

En demandant simplement, un constructeur hérité pourrait-il accéder/initialiser les membres privés de la classe de base? Ou devrais-je les spécifier comme protégés? – Markasoftware

4

Vous devez définir explicitement le constructeur en B et appeler explicitement le constructeur pour le parent.

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

ou

B() : A(5) { } 
80

Constructors ne sont pas héritées. Ils sont appelés implicitement ou explicitement par le constructeur enfant.

Le compilateur crée un constructeur par défaut (un sans arguments) et un constructeur de copie par défaut (un avec un argument qui est une référence au même type). Mais si vous voulez un constructeur qui accepte un int, vous devez le définir explicitement.

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

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

UPDATE: En C++ 11, les constructeurs peut être héritée. Voir la réponse de Suma pour plus de détails.

1

code est

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; 
} 

erreur est b/c classe B a constructeur non paramètre et le second, il devrait avoir initialiseur de classe de base pour appeler le constructeur de la classe de base constructeur de paramètre

3

Ceci est de droit Bjarne Stroustrup's page:

Si vous le souhaitez, vous pouvez toujours vous tirer une balle dans le pied par i nheriting constructeurs dans une classe dérivée dans laquelle vous définissez les nouvelles variables membres qui ont besoin d'initialisation:

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;' au lieu de 'int x;' résoudrait le problème –

+0

@ BЈовић: Oui, c'est la phrase suivante sur la page :) Bjarne –

1

Que diriez-vous d'utiliser une fonction de modèle pour lier tous les constructeurs?

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

probablement vous devriez le faire avec le transfert parfait: modèle B (args && ... args) : A (std :: forward < Args > (args) ...) {} –

+0

Et vous venez de casser le constructeur de copie de Derived'. – Barry

+0

Le constructeur de Base devrait-il aussi être modélisé? Lorsque vous appelez Base (t ...), alors Base devrait être modélisé pour ce que t est? – Zebrafish

Questions connexes