web-dev-qa-db-fra.com

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 protégés dans la classe parent? Je n'arrive pas à le faire marcher. Je peux y remédier, 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!")
    {
    }
};

Quand j'essaye cela, le compilateur me dit: "la classe 'Enfant' n'a pas de champ nommé 'quelque chose'". Est-ce que quelque chose comme ça est possible? Si oui, quelle est la syntaxe?

Merci beaucoup!

117
Stephen

Ce n'est pas possible dans la façon dont vous décrivez. Vous devrez ajouter un constructeur (pouvant être protégé) à la classe de base pour le faire suivre. 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!")
    {
    }
}
110
philsquared

Lorsque le compilateur rencontre la liste des initialiseurs, l’objet de classe dérivée n’a pas encore été formé. Le constructeur de la classe de base n'a pas encore été appelé. Une fois que le constructeur de la classe de base a été appelé, something devient. 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 entraîne l'initialisation par défaut du membre something

De brouillon C++ 0x:

12.6.2 Initialisation des bases et des membres

2 Les noms dans un mem-initializer-id sont leva les yeux dans le champ de la classe du constructeur et, si non trouvé dans ce cadre, sont recherchés dans le champ contenant le .__ du constructeur. définition. [Remarque: si le La classe du constructeur contient un membre avec le même nom que direct ou classe de base virtuelle de la classe, a mem-initializer-id nommant le membre ou classe de base et composé d'un seul identifiant fait référence au membre de la classe . Un meminitializer-id pour le caché La classe de base peut être spécifiée avec un nom qualifié. —Fin note] À moins que le mem-initializer-id nomme le classe du constructeur, une donnée non statique membre de la classe du constructeur ou a base directe ou virtuelle de cette classe, le mem-initializer est mal formé.

Note: Soulignez le mien.

59
dirkgently

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 qu'ils soient protégés, publics ou autres.

Dans votre exemple, 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.

12
AnT

Peut-être que vous pouvez l'essayer de cette manière en utilisant le mot clé "using"

class Parent
{

protected:
std::string something;
};

class Child : public Parent
{

private:
using Parent::something;
Child()
{
    something="Hello, World!";
}
};
0
Aitor