Ordre d'appel de la classe de base constructeur de la classe dérivée de l'initialisation de la liste
struct B { int b1, b2; B(int, int); };
struct D : B {
int d1, d2;
//which is technically better ?
D (int i, int j, int k, int l) : B(i,j), d1(k), d2(l) {} //1st Base
//or
D (int i, int j, int k, int l) : d1(k), d2(l), B(i,j) {} //last Base
};
Ci-dessus est juste le pseudo-code. En réel, je voulais savoir qui ne le ordre d'appel constructeur de base de la matière ?
Il n'existe aucun mauvais comportements (surtout coin des cas) causée par l'un quelconque des cas ? Ma question est plus sur l'aspect technique et pas sur le codage styles.
OriginalL'auteur iammilind | 2011-06-06
Vous devez vous connecter pour publier un commentaire.
L'ordre que vous évoquez dans votre question n'est pas de l'ordre de l'appel de constructeur de base". En fait, vous ne pouvez pas appeler un constructeur. Les constructeurs ne sont pas remboursables par l'utilisateur. Seul compilateur peut appeler les constructeurs.
Ce que vous pouvez faire est de spécifier les initialiseurs. Dans ce cas (constructeur de l'initialiseur de la liste), vous spécifiez les initialiseurs pour les sous-objets de certains des plus grands de l'objet. L'ordre dans lequel vous spécifiez ces initialiseurs n'a pas d'importance: le compilateur va appeler les constructeurs dans un ordre bien précis définis par la spécification du langage, quel que soit l'ordre dans lequel vous spécifiez les initialiseurs. La classe de base des constructeurs sont toujours appelé en premier (dans l'ordre dans lequel les classes de base sont énumérés dans la définition de la classe), puis les constructeurs de membre de la sous-objets sont appelés (encore une fois, dans l'ordre dans lequel ces membres sont énumérés dans la définition de la classe).
(Il y a quelques particularités à cette règle quand il s'agit de virtuel les classes de base, mais j'ai décidé de ne pas les inclure ici.)
Comme pour les mauvais comportements... bien sûr, il ya un potentiel pour les "mauvais comportements" ici. Si l'on suppose que l'ordre de l'initialisation dépend de la commande que vous avez utilisé dans le constructeur de l'initialiseur de la liste, vous aurez probablement éventuellement exécuter dans une désagréable surprise, quand vous découvrez que le compilateur ignore complètement l'ordre et utilise son propre ordre (l'ordre de déclaration) à la place. Par exemple, l'auteur de ce code
pourrait s'attendre à ce
a
être initialisé en premier, etb
de recevoir la valeur initiale de5
dea
, mais dans la réalité cela ne se passe pas depuisb
est initialisé avanta
.et que la classe de base virtuelle initialiseurs sont tout simplement ignorés, sauf si vous êtes la construction de la plus-objet dérivé. Je ne veux pas surcharger ma réponse à ces questions.
"Les constructeurs ne sont pas remboursables par l'utilisateur. Seul compilateur peut appeler des constructeurs." Ne sont pas construtors manuellement appelé avec la mise en place de nouvelles ? Ou est-ce considéré comme "running" du constructeur ?
OriginalL'auteur AnT
La commande est bien définie. Il ne dépend pas de la façon dont vous les spécifiez alors que initializtion.
Constructeur de classe de Base
B
sera appelé en premier et ensuite les variables de membre(d1
&d2
) dans l'ordre dans lequel elles sont déclarées.Pour expliquer le commentaire de @Andrey T réponse.
L'ordre de l'appel de la classe de Base des constructeurs est bien défini par la norme et sera:
La classe de Base virtuelle
MyClass3
, la préférence est donnée au cours de la Classe de BaseMyClass2
.virtual
de la base de commentaire dans la réponse ?pourquoi virtuel de la classe de base, la préférence est donnée au cours de la myclass2.
les classes de base sont donné la préférence parce qu'ils doivent être construits avant toute non-
virtual
des classes de base qui dépendent d'eux. Considérez ceci:struct A{}; struct B : virtual A {}; struct C: virtual A {}; struct D : A, B {};
. Dans ce cas,D
doit construireA
avant de pouvoir construire soitB
ouC
, parce que les deuxB
etC
exiger queA
être construit avant elles sont. Plutôt que de les laisserB
ouC
pour construire leA
(qui pourrait être complexes dans des situations plus complexes, comme si il y avait égalementstruct E : C, B {};
, demandant plus de compilateurles frais généraux et éventuellement introduire un comportement indéterminé (si un simple compilateur décide que
B
toujours constructionsA
, puisE
aurait UB, au motif que sesC
construit avant sonB
peut construire sonA
) ou de la rupture des attentes (si dit compilateur en silence, et du mal, des constructionsB
avantC
, ignorantE : C, B
, alors cela viole le principe de moindre étonnement)), la norme spécifie simplement que la plupart de la classe dérivée doit la construction de toutvirtual
classes de base dans sa hiérarchie d'héritage avant de construire toute non-virtual
les classes de base, garantir queA
sera toujours valide lorsqueB
etC
sont construits, peu importe l'ordre dans lequel ils sont construits, empêchant ainsi toute UB. (Ou, pour raccourcir le mur de texte,virtual
classes de base sont donné la préférence à garantir qu'ils seront toujours valables lorsque la non-virtual
les classes de base de la construction, de la prévention de l'AC et/ou de garder le compilateur de violer la norme pour éviter UB.)OriginalL'auteur Alok Save
L'ordre des choses apparaissent dans la liste d'initialisation n'est pas significative. Dans votre cas, l'objet de base sera toujours initialisé en premier, suivi par d1 et d2, dans cet ordre. L'Initialisation est effectuée dans l'ordre de dérivation et dans l'ordre les membres apparaissent dans la définition de la classe.
Cela dit, il est normalement considéré comme un bon style d'écriture, l'initialisation de la liste dans l'ordre de l'initialisation, et certains compilateurs émet un avertissement si vous ne le faites pas.
OriginalL'auteur Neil Butterworth