herencia de la programacion

32
Herencia 2 2.1. INTRODUCCIÓN La herencia es la característica fundamental que distingue un lenguaje orientado a objetos, como el C++, de otro convencional como C, BASIC, etc. C++ permite heredar las clases características y conductas de una o varias clases denominadas base. Las clases que heredan de clases base se denominan derivadas. Estas a su vez pueden ser clases bases para otras clases derivadas. Se establece así una clasificación jerárquica, similar a la clasificación existente en Biología con los animales y las plantas. La herencia es el concepto que permite a los programadores utilizar de nuevo y extender el código existente. La herencia mejora la confianza en los programas y disminuye el tiempo de desarrollo de los mismos. Los programadores crean clases base: Cuando se dan cuenta de que diversos tipos tienen algo en común, por ejemplo, en el juego del ajedrez, peones, alfiles, rey, reina, caballos y torres son piezas del juego. Creamos, por tanto, una clase base y derivamos cada pieza individual a partir de dicha clase base. Cuando se precisa ampliar la funcionalidad de un programa sin tener que modificar el código existente. 2.2. HERENCIA SIMPLE Hemos estudiado la clase Punto. Vamos ahora a definir una clase que denominaremos PuntoMejorado a partir de Punto, de manera que amplíe su funcionalidad para poder, por ejemplo, desplazar el punto horizontal y verticalmente, y para que las funciones mostrar y ocultar muestren el punto y las coordenadas del punto en la esquina superior izquierda de la pantalla. La relación jerárquica existente entre las dos clases se muestra en la Figura 2. 1. 20

Upload: manuel-felipe-duarte

Post on 14-Nov-2015

224 views

Category:

Documents


0 download

DESCRIPTION

la herencia es la parte de la programacion que permite trabajar por medio de la encapsulacion, y asi tener un codigo mas organizado. Y otras caracteristicas propias de la programacion orientada a objetos.

TRANSCRIPT

  • Herencia

    2 2.1. INTRODUCCIN

    La herencia es la caracterstica fundamental que distingue un lenguaje orientado

    a objetos, como el C++, de otro convencional como C, BASIC, etc. C++ permite

    heredar las clases caractersticas y conductas de una o varias clases denominadas base.

    Las clases que heredan de clases base se denominan derivadas. Estas a su vez pueden

    ser clases bases para otras clases derivadas. Se establece as una clasificacin jerrquica,

    similar a la clasificacin existente en Biologa con los animales y las plantas.

    La herencia es el concepto que permite a los programadores utilizar de nuevo y

    extender el cdigo existente. La herencia mejora la confianza en los programas y

    disminuye el tiempo de desarrollo de los mismos. Los programadores crean clases base:

    Cuando se dan cuenta de que diversos tipos tienen algo en comn, por ejemplo, en el juego del ajedrez, peones, alfiles, rey, reina, caballos y torres son piezas del

    juego. Creamos, por tanto, una clase base y derivamos cada pieza individual a

    partir de dicha clase base.

    Cuando se precisa ampliar la funcionalidad de un programa sin tener que modificar el cdigo existente.

    2.2. HERENCIA SIMPLE

    Hemos estudiado la clase Punto. Vamos ahora a definir una clase que

    denominaremos PuntoMejorado a partir de Punto, de manera que ample su

    funcionalidad para poder, por ejemplo, desplazar el punto horizontal y verticalmente, y

    para que las funciones mostrar y ocultar muestren el punto y las coordenadas del punto

    en la esquina superior izquierda de la pantalla. La relacin jerrquica existente entre las

    dos clases se muestra en la Figura 2. 1.

    20

  • 2.2.1. Clase base

    En la declaracin de la clase base Punto tenemos una nueva palabra protected,

    que significa que las funciones miembro de la clase base y de la clase derivada tienen

    acceso a los miembros dato, pero son prvate (privados) respecto a las funciones

    miembro de otras clases no relacionadas.

    class Punto{

    protected:

    int x;

    int y;

    char ch;

    public:

    Punto (int x1, int y1);

    void mostrar();

    void ocultar ();

    int getx() {return x;}

    int gety(){return y;}

    ~Punto(){cout

  • Punto::Punto (int x1, int yl)

    {

    ch=*;

    x=xl;

    y=yl;

    }

    void Punto::mostrar()

    {

    gotoxy(x,y);

    cout

  • class PuntoMejorado: public Punto{

    public:

    PuntoMejorado (int xl, , int yl);

    void mover (int dx, int dy);

    void mostrar ();

    void ocultar();

    ~ PuntoMejorado(){cout

  • ~Punto() {cout
  • en la clase PuntoMejorado hace, en primer lugar, una llamada a la funcin mostrar

    definida en la clase base Punto, y luego se le aade una conducta particular: esto es, que

    muestre en la esquina superior izquierda de la ventana la abscisa x y la ordenada y del

    punto.

    void PuntoMejorado::mostrar()

    {

    Punto::mostrar();

    gotoxy(1,1);

    cout

  • 2.2.6. Llamada a las funciones que se heredan

    La clase PuntoMejorado hereda los datos y las funciones de la clase base Punto.

    As podemos hacer las siguientes llamadas desde un objeto pm de la clase

    PuntoMejorado.

    pm.mover(-5, 5); //funcin miembro de la clase derivada

    pm.getx(); //funcin miembro de la clase base

    Pero cuando hacemos la llamada,

    pm.mostrar()

    a cul de las dos funciones mostrar se llama? Como podemos comprobar, llama

    a la funcin mostrar redefinida en la clase PuntoMejorado. La funcin mostrar de la

    clase derivada oculta a la funcin mostrar de la clase base. Por lo que la funcin

    mostrar redefinida en la clase derivada est ligada a un objeto de la clase derivada. An

    as, podemos seguir llamando a la funcin mostrar de la clase base Punto desde un

    objeto de la clase derivada, utilizando para ello el operador resolucin de mbito ::.

    pm.Punto::mostrar();

    2.3. POLIMORFISMO

    Polimorfismo es una palabra griega que significa muchas formas. En el lenguaje

    habitual usamos una misma palabra cuyo significado difiere segn sea el contexto. El

    polimorfismo describe una de las facetas ms interesantes y oscuras para los

    principiantes del lenguaje C++: el distinto comportamiento del programa dependiendo

    de la situacin en tiempo de ejecucin de dicho programa.

    El polimorfismo se implementa por medio de las denominadas funciones

    virtuales. Dichas funciones permiten a las clases derivadas proporcionar diferentes

    versiones de la funcin definida en la clase base. En la clase derivada se declara y

    define una funcin que tiene el mismo nombre, el mismo nmero de argumentos y del

    mismo tipo que en la clase base, pero que da lugar a un comportamiento distinto,

    especfico del objeto perteneciente a dicha clase derivada.

    26

  • 2.3.1. La jerarqua de clases que describen las figuras planas

    Consideremos las figuras planas cerradas, como el rectngulo, la elipse, la

    circunferencia o el cuadrado. Tales figuras comparten caractersticas comunes como es

    la posicin de la figura, de su centro y el rea de la figura, aunque el procedimiento para

    calcular dicha rea sea completamente distinto. Podemos, por tanto, disear una

    jerarqua de clases, tal que la clase base denominada Figura tenga las caractersticas

    comunes y cada clase derivada, las especficas. Por otra parte, el crculo es un caso

    particular de la elipse (una elipse especializada), y el cuadrado es un caso especial del

    rectngulo. La relacin jerrquica se muestra en la Figura 2.2.

    La clase Figura es la que contiene las caractersticas comunes a dichas figuras

    concretas, por tanto no tiene forma ni tiene rea. Esto lo expresamos declarando Figura

    como una clase abstracta, declarando y definiendo la funcin miembro rea virtual

    pura.

    class Figura{

    //...

    virtual float rea(void)=0;

    }

    La igualdad a cero es lo que hace que la funcin virtual sea pura. Las clases

    abstractas solamente se pueden usar como clases base para otras clases. No se pueden

    crear objetos pertenecientes a una clase abstracta. Sin embargo, se pueden declarar

    punteros a las clases abstractas y referencias a dichas clases. En el juego del ajedrez

    podemos definir una clase base denominada Pieza, con las caractersticas comunes a

    todas las piezas, como es su posicin en el tablero, y derivar de ella las caractersticas

    especficas de cada pieza particular. As pues, la clase Pieza ser una clase abstracta con

    una funcin virtual pura denominada mover, y cada tipo de pieza redefinir dicha

    funcin de acuerdo a las reglas del movimiento sobre el tablero.

    g La clase Figura

    La clase abstracta Figura, tiene corno miembros la posicin x e y de la figura

    particular, de su centro, y la funcin rea, que se va a redefinir en las clases derivadas

    para calcular el rea de cada figura en particular.

    27

  • Rectngulo

    Crculo

    Elipse

    Cuadrado

    Figura

    Figura 2.2. rbol jerrquico de las figuras planas regulares.

    class Figura{

    protected:

    int x;

    int y;

    public:

    Figura(int _x, int _y);

    virtual ~Figura(){cout

  • g La clase Rectngulo

    Las clases derivadas heredan los miembros dato x e y de la clase base, y

    redefinen la funcin rea, declarada virtual en la clase base Figura, ya que cada figura

    particular tiene una frmula distinta para calcular su rea. Por ejemplo, la clase derivada

    Rectngulo tiene como datos, aparte de su posicin (x, y) en el plano, sus dimensiones,

    es decir, su anchura Lx y altura Ly.

    class Rectangulo:public Figura{

    protected:

    int Lx, Ly;

    public:

    Rectangulo(int _x, int _y, int _Lx, int _Ly);

    ~Rectangulo(){cout

  • g La clase Cuadrado

    La clase Cuadrado es una clase especializada de Rectngulo, ya que un

    cuadrado tiene los lados iguales.

    class Cuadrado:public Rectangulo{

    public:

    Cuadrado(int _x, int _y, int l);

    ~Cuadrado(){cout

  • Elipse::Elipse(int _x, int _y, float rl, float r2)

    :Figura(_x, _y)

    {

    rMayor = rl; rMenor = r2;

    }

    En la redefinicin de la funcin arca, se calcula el rea de la elipse como

    producto del semieje menor por el sernieje mayor por la constante Pi.

    float Elipse::area(void)

    {

    const float PI = 3.1416;

    return PI*rMayor*rMenor;

    }

    g La clase Circulo

    La clase Circulo es una clase especializada de Elipse, ya que una circunferencia

    slo tiene un radio.

    class Circulo:public Elipse{

    public:

    Circulo(int _x, int _y, float r);

    ~Circulo(){cout

  • 2.3.2. Uso de la jerarqua de clases

    Ya hemos visto en el captulo precedente que cuando creamos un objeto elipse

    de la clase Elipse, y llamamos desde l a la funcin rea, se llamar a la funcin rea

    declarada en la clase Elipse.

    Elipse elipse(120, 80, 5.0, 7.2);

    cout

  • enlace tardo para una funcin declarndola virtual. Para comprobar, se crea un array

    de punteros a objetos de la clase base Figura, y se guardan en sus elementos las

    direcciones de objetos de las clases derivadas.

    const int N=4;

    Figura** figura=new Figura* [N];

    figura[0]=new Elipse(120, 80, 5.0, 7.0);

    figura[l]=new Circulo(300, 80, 5.0);

    figura[2]=new Rectangulo(150, 300, 5.0, 7. 0);

    figura[3]=new Cuadrado(300, 300, 7.0);

    La sentencia:

    ptro_Fig[i]area();

    a qu funcin arca llamar? La respuesta ser segn sea el ndice i. Si i es cero,

    el primer elemento del array contiene la direccin de un objeto de la clase Elipse, y

    luego llamar a area de Elipse. Si i es uno, el segundo elemento del array guarda la

    direccin de un objeto de la clase Circulo, luego llamar a area de Circulo, y as

    sucesivamente. Pero si el valor del ndice i se introduce en tiempo de ejecucin (run

    time):

    cin>>i;

    luego la decisin sobre qu funcin area se va a llamar se retrasa hasta el tiempo de

    ejecucin, tal como se muestra en la siguiente porcin de cdigo.

    int i;

    while(1){

    cout

  • cout
  • La principal ventaja de esta formulacin estriba en que la funcin mayor trabaja

    no solamente para una coleccin de crculos y rectngulos, sino tambin para cualquier

    figura derivada de la clase base Figura. As, si se deriva Triangulo de Figura, y se

    aade a la jerarqua de clases, la funcin mayor podr manejar objetos de dicha clase,

    sin modificar para nada el cdigo de la misma.

    Figura* mayor(Figura** f, int n)

    {

    Figura* mFig=0;

    float m=0;

    for( int i=0; im){ m=f[i]->area();

    mFig=f[i];

    }

    //

    //devuelve un puntero al objeto que tiene el valor mayor de su rea

    //

    return mFig;

    }

    Veamos ahora la llamada a la funcin mayor, dentro de main. Primero creamos

    un array de punteros a objetos, guardando en sus elementos las direcciones devueltas

    por new al crear cada figura (objeto de las clases derivadas), del modo que se ha

    explicado en el apartado anterior.

    const int N=4;

    Figura** figura=new Figura* [N];

    figura[0]=new Circulo(300, 80, 5.0);

    figura[1]=new Elipse(120, 80, 5.2, 7.0);

    figura[2]=new Rectangulo(150, 300, 5.0, 7.0);

    35

  • figura[3]=new Cuadrado(300, 300, 7.0);

    Pasamos el array figura y su dimensin a la funcin mayor: el valor que retorna

    lo guardamos en fMayor. Para conocer el valor del rea, desde fMayor se llamar a la

    funcin miembro area. Se llamar a la versin correcta dependiendo del tipo de objeto

    apuntado por fMayor.

    Figura* fMayor=mayor(figura, N);

    Cout

  • Figura* ptr_Fig;

    ptr_Fig=new Rectangulo (150,. 300, 5. 0, 7. 0);

    Cuando se escribe:

    delete ptr_Fig;

    se llamar al destructor de Rectangulo seguido del destructor de Figura. Si el destructor

    no estuviese declarado virtual, se llamara solamente al destructor de Figura,

    destruyendo incorrectamente el objeto al que apunta ptr_Fig. Cuando se destruye el

    array fgura, podemos observar la secuencia de las llamadas a los destructores, primero

    de las clases deriva- das y luego de las clases base Figura.

    for(i=0; i

  • BOOL Valid(const char* entrada);

    };

    TStringLookupValidator

    TRangeValidator

    TFilterValidator

    TValidator

    Figura 2.3. Clases para la verificacin de la informacin.

    Aparte del constructor y destructor, TValidator define dos funciones miembro

    como virtuales puras, que se redefinirn en cada una de las clases derivadas. Estas

    funciones son Error e IsValid. La funcin Valid no ser redefinida en las clases

    derivadas: su papel (en esta simulacin) es la de leer el contenido del control de edicin

    y llamar a la funcin IsValid para verificar si la entrada es correcta. En caso contrario

    emite un mensaje de error.

    BOOL TValidator: :Valid(const char* entrada)

    {

    if(IsValid(entrada)) return TRUE;

    Error() ;

    return FALSE;

    }

    g La clase TFilterValidator

    La clase TFilterValidator tiene como misin filtrar los caracteres que estn

    permitidos. As, si se espera que la entrada sea el nmero del DNI, no se podrn

    introducir caracteres alfabticos. Si en el control de edicin se ha de introducir el

    nombre y apellidos de una persona, no pueden aparecer caracteres numricos, etc.

    38

  • class TFilterValidator: public TValidator{

    protected:

    char* ValidChars;

    public:

    TFilterValidator(char* ValidChars);

    void Error();

    BOOL IsValid(const char* str);

    };

    TFilterValidator tiene como miembro dato el conjunto de caracteres que el

    usuario puede teclear. El constructor crea un objeto de la clase TFilterValidator, reserva

    espacio para el array de caracteres que constituyen el conjunto de caracteres permitidos,

    y copia la cadena de caracteres que se le pasa en el argumento de su constructor en el

    miembro dato ValidChars.

    TFilterValidator::TFilterValidator(char* validChars)

    {

    ValidChars=new char[strlen(validChars)+1];

    strcpy (ValidChars, validChars);

    }

    Redefine la funcin IsValid, de modo que devuelve TRUE si todos los caracteres

    en str estn en el conjunto de caracteres permitidos ValidChars. De otro modo devuelve

    FALSE.

    BOOL TFilterValidator::IsValid(const char* str)

    {

    for(int i=0; i

  • void TFilterValidator::Error()

    {

    cout

  • En la redefinicin de IsValid, se llama primero a la funcin IsValid de la clase

    base a fin de comprobar que se han introducido caracteres numricos. Posteriormente se

    comprueba que el nmero introducido est dentro del intervalo predeterminado.

    BOOL TRangeValidator::IsValid(const char* str)

    {

    if(!TFilterValidator::IsValid(str)) return FALSE;

    int num=atoi(str);

    if (numMax) return FALSE;

    return TRUE;

    }

    Se redefine la funcin miembro Error para emitir un mensaje apropiado

    void TRangeValidator::Error()

    {

    cout

  • public:

    TStringLookupValidator(char** strings, int items);

    ~TstringLookupValidator();

    void Error();

    BOOL IsValid(const char* str);

    }

    El constructor reserva espacio para el array Strings e inicializa los miembros

    dato con la informacin que se le pasa en los argumentos al constructor.

    TStringLookupValidator. :TStringLookupValidator(char** strings, int items)

    :Tvalidator()

    {

    Items=items;

    Strings= new char*[Items];

    for(int i=0; i

  • BOOL TStringLookupValidator::IsValid(const char* str)

    {

    for(int i=0; i

  • public:

    TEdit(int maxChars);

    ~Tedit();

    void SetValidator(TValidator* validator);

    void GetLine(const char* contenido);

    BOOL CanClose();

    };

    En el constructor, reservamos espacio para el array de caracteres intro, e

    inicializamos los otros miembros dato.

    TEdit::TEdit(int maxChars)

    {

    intro= new char[maxChars+1];

    dim=maxChars;

    Validator=0;

    }

    En el destructor liberamos el espacio reservado para el array, y destruimos el

    verificador asociado al control de edicin.

    TEdit::~Tedit()

    {

    delete[] intro;

    delete Validator;

    }

    La funcin SetValidator inicializa el miembro dato Validator con posterioridad a

    la creacin del objeto control de edicin.

    void TEdit::SetValidator(TValidator* validator)

    {

    Validator=validator;

    }

    La funcin GetLine lee los caracteres introducidos en el control de edicin, hasta

    un mximo de dim caracteres. El mximo nmero de caracteres que se pueden

    44

  • introducir en el control de edicin se establece en el constructor. La funcin GetLine

    inicializa el miembro dato intro, con posterioridad a la creacin del objeto control de

    edicin.

    void TEdit::GetLine(const char* contenido)

    {

    if(strlen(contenido)

  • TEdit* editl= new TEdit(20);

    editlSetValidator(new TFilterValidator (abcdefghijklmnftopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVXYZ ,.));

    editlGetLine(Jos Prez Nuez); editl->CanClose();

    En primer lugar se crea el control de edicin pasndole a su constructor el mximo nmero de caracteres que admite, que depende normalmente de la longitud del control

    de edicin en la caja de dilogo. Se asocia al control de edicin un objeto verificador

    de la clase TFilterValidator. Se le pasa al constructor de dicha clase el conjunto de

    caracteres permitidos, en este caso todos los alfabticos del idioma espaol, ms el

    espacio, y los caracteres de puntuacin. La funcin GetLine lee los caracteres que el

    usuario introduce en el control de edicin. La funcin CanClose se llama cuando se

    cierra el dilogo, y en ella tiene lugar todo el proceso de verificacin.

    g El siguiente control de edicin est pensado para introducir un nmero entero.

    TEdit* edit2= new TEdit(5);

    edit2SetValidator(new TRangeValidator(-3, 20)); edit2GetLine(25); edit2CanClose();

    En este caso se asocia al control de edicin un verificador de la clase

    TRangeValidator. Al constructor de dicha clase se le pasa el lmite superior e

    inferior del intervalo, por ejemplo -3 y 20. La funcin GetLine lee los caracteres

    introducidos, que internamente se transforman en nmeros. Dado que el nmero

    introducido, 25, est fuera del intervalo al cerrar el dilogo y llamarse a la funcin

    CanClose de control de edicin, se notificar al usuario que se ha producido un

    error.

    g El siguiente control de edicin est pensado para introducir el nombre de la

    provincia a la que deseamos enviar un paquete postal.

    TEdit* edit3= new TEdit(10);

    char* p[]={Alava, Vizcaya, Guipzcoa};

    46

  • int num=sizeof (p)/sizeof(char*);

    edit3SetValidator(new TStringLookupValidator(p, num)); edit3GetLine(Vizcaya); edit3CanClose();

    Se asocia al control de edicin un objeto de la clase TStringLookupValidator,

    pasndole a su constructor la coleccin de cadenas de caracteres que corresponden

    al nombre de las provincias adonde se piensa enviar los paquetes postales. En el

    caso de que el usuario cometa un error o introduzca el nombre de una provincia

    inexistente, un mensaje de error se lo notifica.

    Como podremos apreciar, la declaracin como virtual de Error y de IsValid en

    la clase base TValidator hace que se llame a la versin correcta cuando se asocia un

    objeto verificador de una clase derivada a un control de edicin. Ms an, podemos

    aadir a la jerarqua clases derivadas de TValidator para el tratamiento de errores

    especficos que ayuden al usuario a verificar que los datos que introduce son los

    esperados antes de su procesamiento por el programa, sin tener que modificar para nada

    el cdigo del control de edicin.

    class TValidator{

    public:

    Tvalidator(){};

    virtual ~Tvalidator(){};

    virtual void Error()=0;

    virtual BOOL IsValid(const char* str)=0;

    BOOL Valid(const char* entrada);

    };

    2.5. HERENCIA MULTIPLE

    En el lenguaje C++, es tambin posible, aunque no es tan frecuente, la herencia

    mltiple. En esta seccin estudiaremos primero el concepto de herencia mltiple, y

    luego abordaremos algunas dificultades que se presentan en jerarquas de clases con una

    nica clase base.

    47

  • 2.5.1. Una clase derivada de otras dos

    Para explicar este concepto, consideremos un ejemplo sencillo. A partir de una

    clase denominada Circulo y otra clase denominada Rectangulo, definimos una nueva

    clase denominada RectRedondo que hereda las caractersticas de ambas clases. La

    clasificacin jerrquica se muestra en la Figura 2.4.

    En la declaracin de las clases base se ha de destacar que el control de acceso a

    los miembros dato se ha establecido como protected, a fin de que las funciones

    miembro de clase derivada RectRectangulo tengan acceso a dichos miembros dato de

    las clases base Circulo y Rectangulo.

    class Circulo{

    protected:

    float radio;

    public:

    Circulo (float r){radio=r;}

    float area(){return radio*radio*3.14;}

    };

    Circulo Rectangulo

    RectRedondo

    Figura 2.4. Herencia mltiple.

    class Rectangulo{

    protected:

    float altura;

    float anchura;

    public:

    Rectangulo (float h, float w) {altura=h;. anchura=w;}

    float mostrar(){return altura;}

    };

    48

  • En la declaracin de la clase derivada observamos la sintaxis de la herencia

    mltiple. Las clases base se ponen una a continuacin de la otra separadas por una

    coma. El modificador de acceso es normalmente public.

    class RectRedondo: public Circulo, public Rectangulo{

    int color;

    public:

    RectRedondo(float h, float w, float r, int c);

    int getcolor(){return color;}

    };

    El constructor de la clase derivada llama a los respectivos constructores de las

    clases base, puestos uno a continuacin del otro separados por una coma. El orden de

    llamada a los constructores es primero al de la clase Circulo y luego al de Rectangulo,

    ya que en este orden figuran en la declaracin de la clase RectRedondo.

    RectRedondo::RectRedondo(float h, float w, float r, int c)

    :Rectangulo(h, w), Circulo(r)

    {

    //...

    }

    La clase derivada hereda los datos y funciones de las clases base. Luego se

    pueden efectuar las siguientes llamadas desde un objeto Rr de la clase derivada

    RectRedondo.

    RectRedondo Rr(15, 3, 5, 0); //objeto de la clase RectRedondo

    cout

  • Rectangulo Circulo

    RectRedondo

    Punto

    Figura 2.5. Herencia mltiple, una nica clase base.

    Cuando creamos un objeto de la clase RectRedondo, se llama a los constructores

    de las clases base Circulo y Rectangulo, pero el constructor de Rectangulo llama al

    constructor de Punto, y el constructor de Circulo tambin llama al constructor de Punto,

    con lo que el constructor de Punto es llamado dos veces. Un objeto de la clase

    RectRedondo tendr dos subobjetos de la clase Punto. Para que esto no cause

    problemas, se le aade la palabra virtual al modificador de acceso de la clase base

    Punto.

    class Circulo: virtual public Punto{

    //...

    };

    class Rectangulo: virtual public Punto{

    //...

    };

    La declaracin de la clase derivada RectRedondo de Circulo y Cuadrado, es la

    misma que hemos visto en el apartado anterior.

    class RectRedondo: public Circulo, public Rectangulo{

    int color;

    public:

    RectRedondo(int a, int b, float h, float w, float r, int c);

    int getcolor(){return color;}

    }

    50

  • 51

    La sintaxis del constructor de la clase RectRedondo adopta la siguiente forma:

    primero se llama al constructor de la clase base Punto, despus al constructor de

    Circulo, a continuacin al de Rectangulo, y por ltimo, al constructor de la propia clase

    RectRedondo.

    RectRedondo::RectRedondo (int a, int b, float h, float w, float r 1 int c)

    :Circulo(a, b, r),Rectangulo(a, b, h, w), Punto(a,b)

    {

    color=c;

    }