Question

Tout d'abord, je veux me faire comprendre que Je ne comprends qu'il n'y a pas de notion vtables et vptrs dans le C ++ standard . Cependant, je pense que pratiquement toutes les implémentations mettre en œuvre le mécanisme d'envoi virtuel dans à peu près de la même façon (corrigez-moi si je me trompe, mais ce n'est pas la principale question). En outre, je crois Je sais comment fonctionnent les fonctions virtuelles , qui est, je peux toujours dire quelle fonction sera appelée, je dois juste les détails de mise en œuvre.

quelqu'un Suppose m'a demandé ce qui suit:
 « Vous avez la classe de base B avec des fonctions virtuelles v1, v2, v3 et classe dérivée D:. B qui Dépasse les fonctions v1 et v3 et ajoute une fonction virtuelle v4 Expliquez comment fonctionne d'expédition virtuelle ».

je répondrais comme ceci:
Pour chaque classe avec des fonctions virtuelles (dans ce cas, B et D), nous avons un tableau séparé de pointeurs-à-fonctions appelées vtable.
Le vtable B contiendrait

&B::v1
&B::v2
&B::v3

Le vtable D contiendra

&D::v1
&B::v2
&D::v3
&D::v4 

Maintenant, la classe B contient un pointeur de membre VPTR. D hérite naturellement et contient donc aussi. Dans le constructeur et destructor des ensembles B B VPTR à un point au vtable de B. Dans le constructeur et destructor de D D, il définit le point au vtable de D'.
Tout appel à une fonction virtuelle f sur un objet x de classe polymorphe X est interprétée comme un appel à x.vptr [Position de f dans vtables]

Les questions sont les suivantes:
1. Ai-je des erreurs dans la description ci-dessus?
2. Comment la position du compilateur f savoir dans vtable (en détail, s'il vous plaît)
3. Est-ce que cela signifie que si une classe a deux bases il a deux vptrs? Ce qui se passe dans ce cas? (Essayer de décrire de la même manière que je l'ai fait, avec autant de détails que possible)
4. Qu'est-ce qui se passe dans une hiérarchie de diamant avec un au-dessus B, C au milieu et D au fond? (A est une classe de base virtuelle de B et C)

Merci à l'avance.

Était-ce utile?

La solution

1. Ai-je des erreurs dans la description ci-dessus?

Toutes les bonnes. : -)

2. Comment le savoir compilateur de position f dans vtable

Chaque fournisseur aura sa propre façon de le faire, mais je pense toujours du vtable comme carte de la signature de la fonction de membre à la mémoire de décalage. Ainsi, le compilateur maintient juste cette liste.

3. Est-ce que cela signifie que si une classe a deux bases il a deux vptrs? Ce qui se passe dans ce cas?

Typiquement, les compilateurs composent un new vtable qui se compose de tous les vtables des bases virtuelles jointes ensemble dans l'ordre où ils ont été spécifiés, de même que le pointeur vtable de la base virtuelle. Ils suivent cela avec les fonctions vtable de la classe dérivateur. Ceci est très fournisseur spécifique, mais pour class D : B1, B2, vous voyez généralement D._vptr[0] == B1._vptr.

héritage multiple

Cette image est en fait pour composer les champs membres d'un objet, mais vtables peut être composé par le compilateur de la même manière exacte (pour autant que je le comprends).

4. Qu'est-ce qui se passe dans une hiérarchie de diamant avec un au-dessus B, C au milieu et D au fond? (A est une classe de base virtuelle de B et C)

La réponse courte? l'enfer absolu. Avez-vous hérité pratiquement les deux bases? Juste un d'entre eux? Aucun d'eux? En fin de compte, les mêmes techniques de composition d'un vtable pour la classe sont utilisés, mais comment cela se fait varie d'une manière extravagante façon, puisque comment il doit être fait est pas du tout ensemble dans la pierre. Il y a une explication décente de résoudre le problème hiérarchie diamant , mais, comme la plupart des cela, il est tout à fait spécifique au fournisseur.

Autres conseils

  1. me semble bon
  2. spécifique de mise en œuvre, mais la plupart ne sont que l'ordre du code source - ce qui signifie l'ordre dans lequel ils apparaissent dans la classe - en commençant par la classe de base, puis en ajoutant de nouvelles fonctions virtuelles de la dérivée. Tant que le compilateur a une façon déterministe de faire cela, alors tout ce qu'il veut faire est très bien. Toutefois, sur Windows, pour créer COM V Tableaux compatibles, il doit être pour source

  3. (pas sûr)

  4. (estimation) Un diamant juste signifie que vous pourriez avoir deux copies d'une classe de base B. L'héritage virtuel va les fusionner en une seule instance. Donc, si vous définissez un membre via D1, vous pouvez le lire via D2. (Avec C dérivée de D1, D2, chacun d'entre eux proviennent de B). Je crois que dans les deux cas, les vtables seraient identiques, que les pointeurs de fonction sont les mêmes - la mémoire des membres de données est ce qui est fusionné
  5. .

Commentaires:

  • Je ne pense pas Destructeurs y entrer!

  • A l'appel, comme par exemple D d; d.v1(); ne sera probablement pas mis en œuvre via le vtable, comme le compilateur peut résoudre l'adresse de fonction à la compilation / link-temps.

  • Le compilateur connaît la position de f parce qu'il a mis là!

  • Oui, une classe avec plusieurs classes de base aura généralement plusieurs vptrs (en supposant des fonctions virtuelles dans chaque classe de base).

  • Scott Meyers livres "Effective C ++" expliquent l'héritage multiple et diamants mieux que moi; Je vous recommande de les lire pour cela (et bien d'autres) raisons. Considérez-les une lecture essentielle!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top