Pourquoi je ne peux pas faire ça?
class A
{
public:
int a, b;
};
class B : public A
{
B() : A(), a(0), b(0)
{
}
};
c++
inheritance
amrhassan
la source
la source
Réponses:
Vous ne pouvez pas initialiser
a
etb
inB
car ils ne sont pas membres deB
. Ils sont membres deA
, donc seulsA
peuvent les initialiser. Vous pouvez les rendre publics, puis les attribuerB
, mais ce n'est pas une option recommandée car cela détruirait l'encapsulation. Au lieu de cela, créez un constructeurA
pour permettreB
(ou une sous-classe deA
) de les initialiser:la source
a
etb
enB::B()
car ils sont privés. Vous ne pouvez pas les initialiser car ils ne sont pas membres declass B
. Si vous les avez rendus publics ou protégés, vous pouvez les attribuer dans le corps deB::B()
.a
etb
..." et l'ai changé en "Vous ne pouvez pas initialiser ..." sans m'assurer que le reste de la phrase avait du sens. Message modifié.En laissant de côté le fait qu'ils sont
private
, depuisa
etb
sont membres deA
, ils sont censés être initialisés parA
les constructeurs de, pas par les constructeurs d'une autre classe (dérivés ou non).Essayer:
la source
D'une manière ou d'une autre, personne n'a énuméré le moyen le plus simple:
Vous ne pouvez pas membres de base accès dans la liste des initialiseur, mais le constructeur lui - même, comme toute autre méthode membre, peut accéder
public
et lesprotected
membres de la classe de base.la source
B
est allouée, puis elle sera affectée à l'intérieur duB
constructeur de. Mais je pense aussi que le compilateur peut toujours optimiser cela.class A
nous ne pouvons pas compter sura
et enb
cours d'initialisation. Toute implémentation declass C : public A
, par exemple, peut oublier d'appelera=0;
et ne pas êtrea
initialisée.class A { int a = 0;};
), soit dans le constructeur de la classe de base. Les sous-classes peuvent toujours les réinitialiser dans leur constructeur si nécessaire.C'est un exemple de travail dans le cas où vous souhaitez initialiser les membres de données de classe de base présents dans l'objet de classe dérivée, alors que vous souhaitez pousser ces valeurs en interface via un appel de constructeur de classe dérivée.
la source
Bien que cela soit utile dans de rares cas (si ce n'était pas le cas, la langue l'aurait permis directement), jetez un œil à l' idiome Base from Member . Ce n'est pas une solution sans code, vous devrez ajouter une couche supplémentaire d'héritage, mais cela fait le travail. Pour éviter le code standard, vous pouvez utiliser l'implémentation de boost
la source
Pourquoi tu ne peux pas le faire? Parce que le langage ne vous permet pas d'initialiser les membres d'une classe de base dans la liste d'initialisation de la classe dérivée.
Comment pouvez-vous y parvenir? Comme ça:
la source
Si vous ne spécifiez pas de visibilité pour un membre de classe, la valeur par défaut est "privée". Vous devez rendre vos membres privés ou protégés si vous souhaitez y accéder dans une sous-classe.
la source
Les classes agrégées, comme A dans votre exemple (*), doivent avoir leurs membres publics et ne pas avoir de constructeurs définis par l'utilisateur. Ils sont initialisés avec la liste d'initialisation, par exemple
A a {0,0};
ou dans votre casB() : A({0,0}){}
. Les membres de la classe d'agrégation de base ne peuvent pas être initialisés individuellement dans le constructeur de la classe dérivée.(*) Pour être précis, comme il a été correctement mentionné, l'original
class A
n'est pas un agrégat en raison de membres privés non statiquesla source