268 votes

Héritage des constructeurs

Pourquoi ce code :

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

class B: public A
{
};

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

Ces erreurs se produisent :

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

B ne devrait-il pas hériter du constructeur de A ?

(en utilisant gcc)

486voto

Suma Points 11966

Si votre compilateur supporte la norme C++11, il y a un héritage de constructeur utilisant using (jeu de mots). Pour en savoir plus, voir Article de Wikipedia sur le C++11 . Vous écrivez :

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

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

C'est tout ou rien - vous ne pouvez pas hériter seulement de certains constructeurs, si vous écrivez ceci, vous héritez de tous les constructeurs. Pour n'hériter que de certains d'entre eux, vous devez écrire les constructeurs individuels manuellement et appeler le constructeur de base si nécessaire.

Historiquement, les constructeurs ne pouvaient pas être hérités dans la norme C++03. Vous deviez les hériter manuellement un par un en appelant l'implémentation de base sur votre propre compte.

21 votes

C'est assez maléfique parce que depuis plus d'un an, il n'existe aucun compilateur capable de construire le code ci-dessus :-)

20 votes

@Mikhail : Clang et g++ devraient maintenant supporter l'héritage des constructeurs : clang.llvm.org/cxx_status.html gcc.gnu.org/projets/cxx0x.html Je recommande de voter pour celle-ci comme étant la bonne réponse.

0 votes

Je demande simplement si un constructeur hérité peut accéder aux membres privés de la classe de base ou les initialiser. Ou devrais-je les spécifier comme étant protégés ?

100voto

Avi Points 14468

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

Le compilateur crée un constructeur par défaut (sans argument) et un constructeur de copie par défaut (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 peuvent être hérités. Voir la réponse de Suma pour plus de détails.

11voto

nenchev Points 57

Cela vient directement de Page de Bjarne Stroustrup :

Si vous le souhaitez, vous pouvez toujours vous tirer une balle dans le pied en héritant des constructeurs d'une classe dérivée dans laquelle vous définissez de nouvelles variables membres nécessitant une 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
}

Notez que vous utilisez une autre grande fonctionnalité de C++11 (initialisation des membres) :

 int x = 77;

au lieu de

int x;

résoudrait le problème

1 votes

int x = 77; au lieu de int x; résoudrait le problème

1 votes

@B : Oui, c'est la phrase suivante sur la page de Bjarne :)

10voto

grepsedawk Points 3413

Vous devez définir explicitement le constructeur dans B et appeler explicitement le constructeur du parent.

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

ou

B() : A(5) { }

1voto

Iqbal Haider Points 34

Le code correct 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;
}

L'erreur est due au fait que la classe B n'a pas de constructeur de paramètres et qu'elle devrait avoir un initialisateur de classe de base pour appeler le constructeur du constructeur de paramètres de la classe de base.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X