Compartir a través de


Clases base virtuales

Dado que una clase puede ser una clase base indirecta a una clase derivada más de una vez, C++ proporciona una manera de optimizar la manera tal trabajo de las clases base.Las clases base virtuales proporcionan una manera de ahorrar espacio y para evitar la ambigüedad en las jerarquías de clases que utilizan herencia múltiple.

Cada objeto no virtual contiene una copia de los miembros de datos definido en la clase base.Esta duplicación pierde el espacio y requiere que se especifique que la copia de los miembros de la clase base desee siempre que les tenga acceso.

Cuando una clase base se especifica como base virtual, puede actuar como base indirecta más de una vez sin la duplicación de sus miembros de datos.Una única copia de los miembros de datos comparten todas las clases base que la utilizan como base virtual.

Al declarar una clase base virtual, la palabra clave de virtual aparece en las listas base de las clases derivadas.

Considere la jerarquía de clases en la ilustración siguiente, que muestra una línea simulada de almuerzo.

Almuerzo-Línea simulada Gráfico

Gráfico Lunch-Line simulado

En la ilustración, Queue es la clase base para CashierQueue y LunchQueue.Sin embargo, cuando ambas clases se combinan para formar LunchCashierQueue, el siguiente problema surge: la nueva clase contiene dos objetos secundarios de Queueescrito, de uno de CashierQueue y otros de LunchQueue.La ilustración siguiente se muestra el diseño conceptual de memoria (el diseño real de memoria se podría optimizar).

objeto simulado de la Almuerzo-Línea

Objeto Lunch-Line simulado

Observe que hay dos objetos secundarios de Queue en el objeto de LunchCashierQueue .El código siguiente declara Queue sea una clase base virtual:

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

La palabra clave de virtual garantiza que sólo una copia del subobjeto Queue se incluya (consulte la ilustración siguiente).

objeto simulado de la Almuerzo-Línea con las clases base de Virtual

Objeto Lunch-Line simulado de clases de VS

Una clase puede tener un componente virtual y un componente no virtual de un tipo determinado.Esto sucede en las condiciones mostrados en la siguiente ilustración.

Componentes virtuales y de no virtual de clase del mismo

Componentes de virtuales y no virtuales de una misma clase

En la ilustración, CashierQueue y uso Queue de LunchQueue como clase base virtual.sin embargo, TakeoutQueue especifica Queue como clase base, no una clase base virtual.Por consiguiente, LunchTakeoutCashierQueue tiene dos objetos secundarios de Queuetipo: uno de la ruta de herencia que incluye LunchCashierQueue y uno de ruta que incluye TakeoutQueue.Esto se muestra en la ilustración siguiente.

Diseño de objetos con herencia de Virtual y de no virtual

Gráfico Virtual_NonvirtualInheritanceObjectLayout

[!NOTA]

La herencia virtual proporciona ventajas importantes de tamaño en comparación con herencia no virtual.Sin embargo, puede introducir una sobrecarga adicional de procesamiento.

Si una clase derivada reemplaza una función virtual que hereda de una clase base virtual, y si un constructor o destructor para las llamadas de la clase base derivada que funcionan con un puntero a la clase base virtual, el compilador puede introducir campos ocultos adicionales de “vtordisp” en las clases con bases virtuales.La opción del compilador /vd0 suprime la adición del constructor de vtordisp/miembro ocultos de desplazamiento del destructor.La opción del compilador /vd1, el valor predeterminado, los habilita donde necesaria.Desactive los vtordisps sólo si está seguro de que todos los constructores de clase y destructores llaman a funciones virtuales virtualmente.

La opción del compilador /vd afecta a un módulo completo de compilación.Utilice el pragma de vtordisp para suprimir y a continuación volver a habilitar campos de vtordisp según la clase-por-clase:

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

Vea también

Referencia

Varias clases base