Herencia virtual

Herencia virtual

En C++, herencia virtual es un tipo de herencia que solventa algunos de los problemas causados por la herencia múltiple (particularmente, el "problema del diamante") mediante la aclaración de la ambigüedad sobre qué miembros de clases padre usar. Es usada cuando la herencia está representando restricciones de un conjunto más que la composición de partes. Una clase base multi-heredada se denota como virtual con la palabra clave virtual.

El problema

Considerando la siguiente jerarquía de clase.

 class Animal {
     virtual void Come();
 };
 
 class Mamífero : public Animal {
  public:
   virtual Color GetColorPelo();
 };
 class AnimalConAlas : public Animal {
  public:
   virtual void Aletea();
 };
 
 // Un murciélago es un mamífero con alas
 class Murciélago : public Mamífero, public AnimalConAlas {};

Pero, ¿cómo Come() un murciélago? Como se ha declarado arriba, una llamada a Murciélago.Come() es ambiguo. Debería llamarse a Murciélago.AnimalConAlas::Come() o a Murciélago.Mamífero::Come(). El problema es que la semántica de la herencia múltiple convencional no modela la realidad. En un sentido, un Animal es Animal sólo una vez; un Murciélago es un Mamífero y un AnimalConAlas, pero un Murciélago es tan Animal por ser Mamífero como por ser AnimalConAlas.

Esta situación es llamada a veces herencia en diamante y es un problema que la herencia virtual intenta, en parte, solventar.

Representación de clases

Antes de seguir es útil tener en cuenta cómo se representan las clases en C++. Concretamente, la herencia es sólo cuestión de poner la clase padre y la clase hija una detrás de la otra en memoria. De esta forma Murciélago es realmente (Animal, Mamífero, Animal, AnimalConAlas, Murciélago), lo que hace que se duplique Animal, causando la ambigüedad.

Solución

Podemos redeclarar nuestras clases de la forma siguiente:

 // Dos clases heredando virtualmente de Animal:
 class Mamífero : public virtual Animal {
  public:
   virtual Color GetColorPelo();
 };
 class AnimalConAlas : public virtual Animal {
  public:
   virtual void Aletea();
 };
 
 // Un murciélago sigue siendo un mamífero con alas
 class Murciélago : public Mamífero, public AnimalConAlas {};

Ahora la parte Animal de Murciélago::AnimalConAlas es la misma que la usada en Murciélago::Mamífero, que es como decir que un Murciélago sólo tiene un Animal en su representación y por tanto llamar a Murciélago::Come() no es ambiguo.

Esto se implementa ofreciendo Mamífero y AnimalConAlas con una vtable ya que, por ejemplo, el desplazamiento de memoria entre el comienzo de un Mamífero y de su parte Animal no se conoce hasta el momento de la ejecución del programa. De esta forma Murciélago pasa a ser (vtable*, Mamífero, vtable*, AnimalConAlas, Murciélago, Animal).

Con dos punteros vtable (vtable*) por objeto, el tamaño del objeto aumenta en dos punteros, pero así sólo hay un Animal y no hay ambigüedad. Hay un puntero Animal por cada herencia que hereda virtualmente de Animal: Mamífero y AnimalConAlas. Todos los objetos del tipo Murciélago tendrán los mismos vtable*, pero cada objeto Murciélago contendrá un único objeto Animal propio. Si otra clase hereda de Mamífero, como Ardilla, la vtable* en el objeto Mamífero de Ardilla será diferente del vtable* en el objeto Mamífero de un Murciélago, aunque podrían ser esencialmente el mismo en el caso especial de que la parte Ardilla del objeto tuviera el mismo tamaño que la parte Murciélago, ya que la distancia desde la parte Mamífero hasta la parte Animal sería la misma. Las vtables no son realmente las mismas, pero la información esencial en ellas (la distancia), sí lo es.


Wikimedia foundation. 2010.

Игры ⚽ Поможем решить контрольную работу

Mira otros diccionarios:

  • Virtual — y virtualidad, lo opuesto a lo real y a la realidad, pueden referirse a: Partícula virtual Temperatura virtual Realidad virtual Mundos virtuales Imagen virtual Función virtual Sexo virtual Mascota virtual Bien virtual Herencia virtual… …   Wikipedia Español

  • Herencia genética — La herencia genética es la transmisión a través del material genético contenido en el núcleo celular, de las características anatómicas, fisiológicas o de otro tipo, de un ser vivo a sus descendientes. El ser vivo resultante tendrá… …   Wikipedia Español

  • Función virtual — En programación orientada a objetos (POO), una función virtual o método virtual es una función cuyo comportamiento, al ser declarado virtual , es determinado por la definición de una función con la misma cabecera en alguna de sus subclases. Este… …   Wikipedia Español

  • Problema del diamante — Saltar a navegación, búsqueda Un diagrama de herencia en diamante. En los lenguajes de programación orientada a objetos, el problema del diamante es una ambigüedad que surge cuando dos clases B y C heredan de A, y la clase D hereda de B y C. Si… …   Wikipedia Español

  • Carlos I de España — Para otros monarcas con el nombre de Carlos I, véase Carlos I (desambiguación). «Carlos V» redirige aquí. Para otras acepciones, véase Carlos V (desambiguación). Carlos I de España y V del Sacro Imperio Romano Germánico Emperador del Sacro… …   Wikipedia Español

  • C++ — Desarrollador(es) Bjarne Stroustrup, Bell Labs Información general …   Wikipedia Español

  • Bujalance — Saltar a navegación, búsqueda Para otros usos de este término, véase Bujalance (desambiguación). Bujalance …   Wikipedia Español

  • Historia de las islas Malvinas — Saltar a navegación, búsqueda Mapa de las islas Malvinas, con la toponimia argentina. Las islas Malvinas son un archipiélago ubicado en el mar Argentino, en el océano Atlántico Sur, a una distancia mínima de la Patagonia d …   Wikipedia Español

  • Historia de las Islas Malvinas — Este artículo o sección puede ser demasiado extenso(a). Algunos navegadores pueden tener dificultades al mostrar este artículo. Por favor, considera separar cada sección por artículos independientes, y luego resumir las secciones presentes en… …   Wikipedia Español

  • Jean-Baptiste Lamarck — Retrato de Jean Baptiste Lamarck Nacimiento 1 de agosto de 1744 Bazentin, Picardía …   Wikipedia Español

Compartir el artículo y extractos

Link directo
Do a right-click on the link above
and select “Copy Link”