Titulo.jpg (10742 bytes)
FlechaI.jpg (2886 bytes) casa.jpg (31539 bytes) FlechaD.jpg (2791 bytes)

Herencia múltiple

Problemas de la herencia multiple

        Nombres iguales

        Herencia doble

        Herencia virtual


Otra situación muy común que se presenta ante un programador es la de integrar en un objeto propiedades y funciones provenientes de clases que no tienen vínculo entre si.

Practicamente todos los problemas de cierta envergadura requieren integrar las caracteristicas de diferentes elementos como pueden ser: figuras, texto, comportamientos físicos para que la computadora actue como lo hacen los sistemas en la vida real.

Un ejemplo simple pero muy ilustrativo es la creación de un icono.

Supongamos que tenemos una clase TIconoFuente, que contiene los elementos gráficos pero un icono debe tener un nombre que lo identifique de manera que a TIconoFuente no le basta con heredar de TCirculo sino que también necesitaría hacerlo de una clase que le brinde la posibilidad de escribir en modo gráfico.

Así tenemos que necesitamos en TIconoFuente la concurrencia de la clase TCirculo y de TEscribeG, conteniendo esta última clase las propiedades y funciones necesarias para escribir en modo gráfico.

Quedaría entonces TIconoFuente como sigue:

class TIconoFuente : public TCirculo, public TEditor

{ private : char *Cadena;
  public: TIconoFuente (float PosxP,float PosyP,float radioP,char CadenaP[50],unsigned int ColorP=WHITE) :
             TCirculo (PosxP,PosyP, radioP, ColorP=WHITE),
             TEditor(PosxP-15,PosyP+15)
              {Cadena = CadenaP;}
   virtual void Muestra (void);
   virtual void Borra (void);
};

void TIconoFuente::Muestra ()
{ TCirculo :: Muestra();
  EscribirG(Cadena);
  for(float i=0;i<6.14;i+=0.01)
       { ~ ~ ~ ~
       }
}
 
void TIconoFuente::Borra ()
{ ~ ~ ~ ~ }

Como se ve en la herencia multiple se requiere que en la declaración de la clase heredera aparezca el llamado a las funciones constructoras de todas aquellas clases de las que se hereda y consecuentemente que en el constructor de la que hereda aparezcan todos los parametros que requieren estos constructores.

Hay que decir que la sintáxis de la herencia es muy simple y es muy similar para cuando heredamos de una sola clase o de varias.

Problemas de la herencia multiple

Una de las razones de ser de la POO, es la posibilidad de usar clases hechas por diferentes personas e integrarlas en un sistema único, habiendo sido este a su vez diseñado por alguien que no conoce las interioridades de los elementos que esta usando. Solo se necesita saber que necesitan las clases para funcionar y que resultado entregan.

Sin embargo cuando el entramado de clases se agranda pueden ocurrir algunos conflictos que deben ser previstos y en lo posible evitados.

Nombres iguales

Dado que estamos tomando clases hechas por distintas personas, posiblemente con objetivos similares, es muy posible que hayan usado para funciones diferentes nombres iguales. Si las funciones entregan o reciben datos diferentes no existirian problemas ya que el compilador de C++ puede identificar a que función nos referimos, pero si ambas funciones son del mismo tipo y tienen iguales parametros no sabriamos a cual de ellas nos estamos refiriendo.

La posibilidad de heredar de forma private resuelve esta situación.

class X : private Y, private Z

{ ~ ~ ~ ~
  public : ~ ~ ~ ~
  tipo YA {return Y::A(...);}
  tipo ZA {return Z::A(...);}
  ~ ~ ~ ~
};

esquematicamente vemos que las clases Y y Z posee cada una de ellas una función llamada A que tiene los mismos parametros y devuelve el mismo tipo de dato. Como que heredamos de manera private los objetos de X "no ven" las funciones A() ni de Y ni de Z pero si ven a YA() y ZA() de X. Esas funciones simplemente llaman a las A() de las clases de las que se hereda y de esa manera el cliente de X no tiene que conocer de donde proceden los recursos que esta usando con lo que mantenemos la rehusabilidad del recurso y preservamos su encapsulamiento.

Por supuesto tenemos un costo adicional de tiempo pues se esta realizando un doble llamado a las funciones.

Herencia doble

Por las mismas razones que hemos mencionado antes podemos tener la siguiente situación.

Las clases TRectangulo y TCirculo heredan de TPunto y TIcono hereda de forma multiple de TRectangulo y TCirculo, de esta manera TIcono contiene dos veces a TPunto.

Como sabemos cuando hacemos un objeto deTPunto estaremos haciendo un objeto TRectangulo y otro TCirculo y consecuentemente dos TPunto. Eso nos lleva a que los datos de la clase TPunto se duplican y también sus funciones. Si se ha aplicado correctamente la POO todos los datos serán modificados o leidos por funciones de manera que una vez resuelto el problema para las funciones queda resuelto para los datos.

Al igual que en el para resolver el problema de nombres iguales aquí podemos hacer referencia a las funciones invocando por que vía queremos llegar a la función de TPunto.

class TIcono : public TCirculo, public TRectangulo
{ ~ ~ ~ ~
public : ~ ~ ~ ~
TCirculo::Traslada();
TRectangulo::MiX();
~ ~ ~ ~
};

de esta forma estaremos utilizando la función Traslada() contenida en TPunto por la vía de TCirculo y a MiX() por TRectangulo.

Cualquier intento ya sea en TIcono o en un programa atraves de un objeto de esa clase de ejecutar directamente a Traslada() o a MiX() dara error de compilación.

Como quiera que las clases TCirculo y TRectangulo se pueden haber hecho por programadores diferentes y no necesariamente pensando en que van a ser heredadas de forma multiple por un tercero este es un problema que puede presentarse en cualquier momento en la POO.

Herencia virtual

Una posibilidad que brinda C++ para evitar estos conflictos es que TCirculo y TRectangulo hereden de TPunto de forma virtual

class TRectangulo : virtual public TPunto
{~ ~ ~ ~

class TCirculo : virtual public TPunto
{~ ~ ~ ~
}

ahora podemos hacer

class TIcono : public TRectangulo, public TCirculo

{ public : traslada();

}

sin que se generen conflictos. Si bien esto resuelve el anterior problema trae como consecuencia que impide al programador heredar doble, si este necesita tener el objeto Punto visto al mismo tiempo desde la óptica de TRectangulo y desde la de TCirculo. El programador deberá seleccionar entre una de las dos limitaciones.

arriba.jpg (2978 bytes) casa.jpg (31539 bytes)
Hosted by www.Geocities.ws

1