2010-04-12 5 views
3

contexte 1: classe D: public B1, public B2 {};Utiliser l'adresse/pointeur de la super classe dans la liste d'initialisation

contexte 2: B2 prend B1 pour initialiser: B2 (B1 *) // constructeur de B2

ma question est dans la liste d'initialisation de D':

D :: D(): B1(), B2 (?) ... Qu'est-ce qui devrait être?

Je ne veux pas mettre "(B1 *) ceci" dans le? placer, car il ne sert à rien d'utiliser "this" dans la liste d'initialisation. Et puisque la partie B1 a été initialisée, il est logique de l'utiliser.

Que dois-je faire?

Répondre

3

Vous pouvez utiliser la partie B1 de this car elle est déjà initialisée. §12.6.2/5: "les classes de base directes doivent être initialisées dans l'ordre de la déclaration telles qu'elles apparaissent dans la liste de spécification de base (indépendamment de l'ordre des initialiseurs)."

La liste de spécification de base est class D : public B1, public B2 et la liste mem-initializer est D::D() : B1(), B2(…). Je dirais que cela a «l'odeur du code», cependant.

EDIT: Maintenant, je comprends votre préoccupation, si this n'est pas défini à l'extérieur du corps du constructeur, qui ne comprend pas les initialiseurs membres. Le langage permettant cela est enterré entre deux exemples et je l'ai manqué au début. Paragraphe 7: "Les noms dans la liste d'expression d'un mem-initialiseur sont évalués dans la portée du constructeur pour lequel le mem-initializer est spécifié."

Si B2 a réellement besoin de conserver un pointeur sur un B1, et ce pointeur pointe toujours à l'intérieur de l'objet le plus dérivé, pensez héritage virtuel.

class B1 {}; 
class B2 : virtual B1 {}; // under the hood, B2 has a pointer to B1. 
class D : public virtual B1, public B2 {}; // D has a pointer too 
// Only the most-derived class (the one actually used for instantiation) 
// implements space for and initialization of the B1. 
+0

Dans mon cas, B1 et B2 ne sont pas dans une relation d'héritage, je ne veux pas changer B2 dans le but de résoudre ce problème. –

1

Ceci est du code risqué. Comme indiqué précédemment, B1 est construit avant B2, donc vous pouvez le faire en toute sécurité, mais si la définition de la classe change ce ne sera plus le cas, et il est dans un endroit sans rapport dans le code, de sorte que vous ne pouvez pas voir le code que vous cassez quand vous le cassez.

Je regarderais de près ce design - est-il possible de le changer pour le rendre inutile? Pouvez-vous déplacer les choses dans les membres pour encapsuler plutôt que d'hériter - D est-il vraiment un B1 et un B2?

+0

Il est courant de voir qu'un membre est dépendant d'un autre. Si la définition change, les développeurs ont la responsabilité de changer d'implémentation. Je pourrais changer de design, c'est facile, mais je veux découvrir le côté technique de ce problème, parce que c'est logique. –

+0

@JQ: vous avez dit "membre" au lieu de "base". S'ils sont membres, vous n'avez pas ce problème. Sont-ils? – Potatoswatter

+0

@Potatoswatter: Encore une fois, je répète: "Je pourrais changer de design, c'est facile, mais je veux découvrir le côté technique de ce problème, parce que c'est logique" –