149 votes

Initialiser les membres protégés du parent avec la liste d'initialisation (C++)

Est-il possible d'utiliser la liste d'initialisation du constructeur d'une classe enfant pour initialiser les membres de données déclarés comme protégés dans la classe parentale ? Je n'y parviens pas. Je peux le contourner, mais ce serait bien si je n'avais pas à le faire.

Quelques exemples de code :

class Parent
{
protected:
    std::string something;
};

class Child : public Parent
{
private:
    Child() : something("Hello, World!")
    {
    }
};

Lorsque j'essaie de le faire, le compilateur me dit : "class 'Child' does not have any field named 'something'" (la classe 'Child' n'a pas de champ nommé 'quelque chose'). Est-il possible de faire quelque chose comme cela ? Si oui, quelle est la syntaxe ?

Merci beaucoup !

143voto

philsquared Points 13547

Ce n'est pas possible de la manière que vous décrivez. Vous devrez ajouter un constructeur (qui pourrait être protégé) à la classe de base pour la transmettre. Quelque chose comme :

class Parent
{
protected:
    Parent( const std::string& something ) : something( something )
    {}

    std::string something;
}

class Child : public Parent
{
private:
    Child() : Parent("Hello, World!")
    {
    }
}

5 votes

C'est exactement la solution que j'avais déjà trouvée. Au moins, je n'ai plus à me demander si c'est faisable ou non :)

73voto

dirkgently Points 56879

Lorsque le compilateur rencontre la liste des initialisateurs, l'objet de la classe dérivée n'est pas encore formé. Le constructeur de la classe de base n'a pas encore été appelé. Ce n'est qu'après que le constructeur de la classe de base a été appelé, something naît. D'où le problème. Lorsque vous n'appelez pas explicitement le constructeur de la classe de base, le compilateur le fait pour vous (en générant le constructeur trivial approprié pour la classe de base). Cela provoque l'apparition du something à initialiser par défaut.

Extrait du projet C++0x :

12.6.2 Initialisation des bases et des membres

2 Les noms contenus dans un mem-initializer-id sont les suivants sont recherchés dans la portée du du constructeur et, s'ils ne sont pas trouvés dans cette portée, ils sont recherchés dans la portée contenant la classe du constructeur. [Remarque : si la classe du contient un membre w- U''

N

3 votes

T

19voto

AndreyT Points 139512

Vous ne pouvez pas initialiser les membres de la classe parente dans la liste d'initialisation du constructeur de la classe dérivée. Peu importe où ils sont protégés, public ou quoi que ce soit d'autre.

Dans votre exemple, le membre something est membre de la classe Parent , ce qui signifie qu'il ne peut être initialisé que dans la liste d'initialisation du constructeur de la classe Parent .

2voto

Neha Kumari Points 8

J'ai rencontré un problème similaire et voici la solution que j'ai trouvée

class Parent

{
protected:
    std::string something;
};

class Child : public Parent
{
private:
    Child()
    {
       something="Hello, World!";
    }
};

Y a-t-il un problème avec l'approche ci-dessus ?

0voto

Daniel C Jacobs Points 141

Comme l'a dit @philsquared, vous ne pouvez pas initialiser les membres d'une classe parentale à partir de la liste d'initialisation des membres de la classe enfant, mais vous pouvez ajouter un constructeur de classe parentale et appeler ce constructeur à partir de la liste d'initialisation des membres de la classe enfant.

Et comme l'a dit @dirkgently, la raison pour laquelle vous ne pouvez pas initialiser les membres de la classe parente dans la liste d'initialisation est qu'à ce stade, le constructeur de la classe parente n'a pas encore été appelé, de sorte que ces champs ne sont pas disponibles.

Pour la postérité, je voulais également souligner que si vous ne voulez pas écrire un constructeur pour votre classe mère, vous pouvez simplement initialiser les membres protégés dans le corps du constructeur :

class Child : public Parent
{
private:
    Child() {
        something = "Hello, World!";
    }
};

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