Partager via


Classes de bases virtuelles

Étant donné qu'une classe peut être une classe de base indirecte à une classe dérivée plusieurs fois, C++ permet d'optimiser la façon dont un tel travail de classes de base.Les classes de base virtuelle offrent un moyen de libérer de l'espace et d'éviter les ambiguïtés dans les hiérarchies de classes qui utilisent un héritage multiple.

chaque objet non virtuel contient une copie des données membres définies dans la classe de base.Cette duplication gaspille l'espace et requiert que vous indiquiez que la copie des membres de la classe de base à chaque fois que vous accédez.

Lorsqu'une classe de base est spécifiée comme base virtuelle, il peut agir comme base indirecte plusieurs fois sans duplication de ses données membres.Une même copie de ses données membres est partagée par toutes les classes de base qui l'utilisent comme base virtuelle.

Lorsque vous déclarez une classe de base virtuelle, le mot clé de virtuel apparaît dans les listes de base des classes dérivées.

Examinez la hiérarchie de classes dans l'illustration suivante, qui montre une ligne simulée de déjeuner.

Déjeuner-Ligne simulée Graphique

Graphique Lunch-Line simulée

dans l'illustration, Queue est la classe de base pour CashierQueue et LunchQueue.Toutefois, lorsque les deux classes sont combinées pour former LunchCashierQueue, le problème suivant s'affiche : la nouvelle classe contient deux sous-objets de type Queue, un d' CashierQueue et d'autres LunchQueue.L'illustration suivante montre la disposition conceptuelle de mémoire (la disposition réelle de la mémoire peut être optimisées).

objet simulé de Déjeuner-Ligne

Objet Lunch-Line simulé

Notez qu'il existe deux sous-objets d' Queue dans l'objet d' LunchCashierQueue .Le code suivant déclare Queue pour être une classe de base virtuelle :

// deriv_VirtualBaseClasses.cpp
// compile with: /LD
class Queue {};
class CashierQueue : virtual public Queue {};
class LunchQueue : virtual public Queue {};
class LunchCashierQueue : public LunchQueue, public CashierQueue {};

Le mot clé d' virtual garantit qu'une copie du sous-objet Queue est incluse (voir la figure suivante).

Objet simulé de Déjeuner-Ligne avec les classes de base virtuelle

Objet Lunch-Line simulé de classes VS

Une classe peut avoir un composant virtuel et un composant non virtuelle d'un type donné.Cela se produit dans les conditions suivantes dans l'illustration suivante.

composants virtuels et non virtuels de la même classe

Composants virtuels et non virtuels d'une même classe

dans l'illustration, CashierQueue et LunchQueue utilisent Queue comme classe de base virtuelle.Toutefois, TakeoutQueue spécifie Queue comme classe de base, et non une classe de base virtuelle.par conséquent, LunchTakeoutCashierQueue a deux sous-objets de type Queue: un du chemin d'accès d'héritage qui inclut LunchCashierQueue et un du chemin d'accès qui inclut TakeoutQueue.ceci est illustré dans l'illustration suivante.

Disposition des objets avec l'héritage virtuel et non virtuel

Graphique Virtual_NonvirtualInheritanceObjectLayout

[!REMARQUE]

L'héritage virtuel fournit les avantages significatifs de taille en comparaison avec l'héritage non virtuel.Toutefois, il peut présenter certaines de traitement supplémentaire la charge mémoire.

Si une classe dérivée substitue une fonction virtuelle qu'elle hérite d'une classe de base virtuelle, et si un constructeur ou un destructeur pour les appels de classe de base dérivée qui s'exécutent à l'aide d'un pointeur vers la classe de base virtuelle, le compilateur peut introduire des champs masqués supplémentaires « vtordisp » dans les classes avec des bases virtuelles.L'option du compilateur /vd0 supprime l'ajout du membre masqué de décalage de constructeur/destructeur de vtordisp.L'option du compilateur /vd1, la valeur par défaut, les vérifie où ils sont nécessaires.Désactivez les vtordisps uniquement si vous êtes certain que tous les constructeurs et de destructeurs de classe appellent des fonctions virtuelles pratiquement.

L'option du compilateur /vd affecte un module entier de compilation.Utilisez le pragma de vtordisp pour supprimer puis revalider des champs de vtordisp sur une base de classe-par-classe :

#pragma vtordisp( off )
class GetReal : virtual public { ... };
#pragma vtordisp( on )

Voir aussi

Référence

Plusieurs classes de base