• No se han encontrado resultados

Tema 6: Herencia. (El lenguaje C++)

N/A
N/A
Protected

Academic year: 2021

Share "Tema 6: Herencia. (El lenguaje C++)"

Copied!
11
0
0

Texto completo

(1)

(El lenguaje C++)

Tema 6: Herencia

(El lenguaje C++)

Tema 6: Herencia 1

1.

1.

1.

1. Herencia. Herencia. Herencia. Herencia.

2. Miembros protegidos.

3. El constructor de la clase derivada.

Índice Índice Índice Índice

Tema 6: Herencia

4. Redefinición de funciones miembro.

5. Herencia múltiple.

6. Conversiones entre clases base y clases derivadas.

2

(2)

• En C++ pueden ser definidas clases en términos de otras clases (composición).

• En C++ también podemos definir una clase a partir de otra preexistente utilizando la herencia de clases.

• La herencia es una técnica de reutilización del software en la que se crean clases a partir de clases ya existentes por medio de la absorción de sus atributos y métodos, modificando aquellos que requiera la nueva clase o introduciendo nuevas capacidades.

1. Herencia 1. Herencia 1. Herencia 1. Herencia

introduciendo nuevas capacidades.

• Al crear una nueva clase, el programador puede indicar que esta clase va a

“heredar” los atributos y métodos de una clase ya existente que se llama clase base. La nueva clase se conoce como clase derivada.

• La clase derivada tiene todas las funcionalidades de la clase base (hereda sus atributos y métodos).

• Aparte, la clase derivada introduce nuevas funcionalidades (nuevos atributos y métodos).

• La clase base es más general y la clase derivada más específica.

3

Vehículo

V_Tierra V_Mar

Coche

V_Aire

Indica qué tienen en común todos los vehículos.

+ General - funcionalidad

- General (+ Concreta) + funcionalidad

Tienen aspectos diferenciadores.

Coche es un tipo especial de vehículo de Tierra, que es un tipo especial de Vehículo.

1. Herencia 1. Herencia 1. Herencia 1. Herencia

class Vehiculo { public:

Vehiculo() { peso = 0; } Vehiculo(int p) { peso = p; } int setPeso(int p) {

peso=p;

}

int getPeso() const { return peso;

} private:

int peso;

};

que es un tipo especial de Vehículo.

Clase vehículo: almacena el peso del vehículo.

(3)

• Queremos representar un vehículo que viaje sobre tierra, para ello definimos una nueva clase: V_Tierra, que tendrá:

Las funcionalidades de la clase Vehículo (peso)

+

Información adicional: velocidad del vehículo.

• El vehículo de tierra es un tipo especial de vehículo: la relación entre ellos más natural es la de la herencia.

• La clase V_Tierra derivará de la clase Vehiculo (clase base).

1. Herencia 1. Herencia 1. Herencia 1. Herencia

• La clase V_Tierra derivará de la clase Vehiculo (clase base).

• Sintaxis para la derivación:

class B: public A

(la clase B deriva de A)

class V_Tierra : public Vehiculo {

public:

V_Tierra(); //Constructor.

V_Tierra(int p, float v);

//interface

void setVelocidad (float v) { velocidad = v; } float getVelocidad() const { return velocidad; }

float MomentoInercia() { return getPeso()*velocidad; } private:

float velocidad;

}; Método público de Vehiculo

La clase V_Tierra contiene:

las funcionalidades de la clase base Vehiculo más nuevas funcionalidades

5

• Ejemplo de utilización de la clase derivada:

int main() {

V_Tierra vehi(1200,145.3);

cout << "Peso del vehículo" << vehi.getPeso()

<< "Velocidad del vehiculo”<< vehi.getVelocidad();

return(0);

}

• Vemos dos características de la derivación:

1. Herencia 1. Herencia 1. Herencia 1. Herencia

Tema 6: Herencia

• Vemos dos características de la derivación:

 Los miembros públicos de la clase base (ej. getPeso()) son heredados como públicos dentro de la clase derivada.

 La función getPeso() no es un miembro directo de la clase V_Tierra. Esta función es un miembro implícito de esta clase, heredado de su clase padreVehiculo.

 Los miembros privados de la clase base (ej. peso) son heredados como privados dentro de la clase (V_Tierr). NO son accesibles por las funciones definidas fuera de la clase base, NI SIQUIERA por las funciones de la clase derivada.

 Las funciones miembro de la clase derivada (ej. MomentoInercia()) sólo pueden acceder a ellos a través del interfaz público (getPeso()).

6

(4)

Una clase derivada (ej. V_Tierra) puede ser a su vez la clase base de otras nuevas clases:

class Coche : public V_Tierra {

public:

//constructores Coche();

Coche(int p, int v, const string &n);

//constructor de copia

Derivación anidada: Coche deriva de V_Tierra que deriva de Vehiculo.

1. Herencia 1. Herencia 1. Herencia 1. Herencia

Tema 6: Herencia

//constructor de copia

Coche ( const Coche & otro);

//interfaz

string getNombre() const;

void setNombre(const string &n);

private:

string nombre;

};

7

1. Herencia.

2. 2.

2. 2. Miembros protegidos. Miembros protegidos. Miembros protegidos. Miembros protegidos.

3. El constructor de la clase derivada.

Índice Índice Índice Índice

4. Redefinición de funciones miembro.

5. Herencia múltiple.

6. Conversiones entre clases base y clases

derivadas.

(5)

• Los miembros públicos de la clase base son accesibles desde

cualquier función del programa, incluidas las funciones miembro de la clase derivada.

• Los miembros privados sólo son accesibles por las funciones miembro de la clase base, y por los amigos de la clase base. Estos miembros no son accesibles por las funciones de la clase derivada.

• En C++ existe además de éstos un nivel intermedio de

2. Miembros protegidos 2. Miembros protegidos 2. Miembros protegidos 2. Miembros protegidos

• En C++ existe además de éstos un nivel intermedio de proteccion entre el acceso público y el privado: protected.

• Los miembros clasificados como protected en la clase base son accesibles por los miembros de las clases derivadas y por sus amigos.

• Se comportan como public para los métodos de la clase derivada y amigas, y como private para el resto de funciones.

• Desde la clase derivada podemos hacer referencia a miembros públicos y protegidos de la clase base simplemente utilizando los nombres de éstos.

9



Si resulta imprescindible el acceso directo a los miembros privados de la base dentro de los métodos de la clase derivada, éstos deberán ser reclasificados como protegidos:

class Vehiculo { ...

protected:

int peso;

};

Atributo protegido

2. Miembros protegidos 2. Miembros protegidos 2. Miembros protegidos 2. Miembros protegidos

Tema 6: Herencia class V_Tierra : public Vehiculo

{

...

float MomentoInercia() const { return peso * velocidad;

} ...

private:

float velocidad;

};

Atributo privado de V_Tierra

Atributo protegido de Vehiculo

10

(6)

1. Herencia.

2. Miembros protegidos.

3.

3.

3.

3. El constructor de la clase derivada. El constructor de la clase derivada. El constructor de la clase derivada. El constructor de la clase derivada.

Índice Índice Índice Índice

Tema 6: Herencia 11

4. Redefinición de funciones miembro.

5. Herencia múltiple.

6. Conversiones entre clases base y clases derivadas.



Veamos los efectos de la herencia en el constructor de la clase deriv.



Un objeto de una clase derivada contiene todos los atributos de la clase base.



Para inicializarlos de forma correcta el constructor de la clase derivada invoca al constructor de la clase base.

3. El constructor de la clase derivada 3. El constructor de la clase derivada 3. El constructor de la clase derivada 3. El constructor de la clase derivada

derivada invoca al constructor de la clase base.

 Automáticamente, sin necesidad de indicarlo explícitamente en el código: Se invoca al constructor por defecto de la clase base

 Indicándolo de forma explícita en el código: Constructor con argumentos de la clase base.



Al crear un objeto de la clase derivada, se ejecuta primero el

constructor de la clase base y luego el de la clase derivada.

(7)



Automáticamente

El constructor de V_Tierra se podría implementar así:

V_Tierra :: V_Tierra( int p, int v) {

setPeso(p);

setVelocidad (v);

}



El compilador de C++ genera el código para llamar al constructor por defecto de la clase base cada vez que es llamado un constructor de una derivada. Es decir:

3. El constructor de la clase derivada 3. El constructor de la clase derivada 3. El constructor de la clase derivada 3. El constructor de la clase derivada

LLama automáticamente al constructor por defecto de la clase Vehiculo

derivada. Es decir:

 Primero se llama al constructor por defecto de la clase Vehículo, que probablemente inicializará la variable peso.

 Después se cambia el valor de peso llamando a la función setPeso.



De forma explicita (una mejor solución para el ej anterior)

V_Tierra :: V_Tierra (int p, int v) : Vehiculo(p)

{

setVelocidad(v);

13 }

LLama explicitamente al constructor de la clase Vehiculo con argumento.

1. Herencia.

2. Miembros protegidos.

3. El constructor de la clase derivada.

Índice Índice Índice Índice

Tema 6: Herencia 14

4.

4.

4.

4. Redefinición de funciones miembro. Redefinición de funciones miembro. Redefinición de funciones miembro. Redefinición de funciones miembro.

5. Herencia múltiple.

6. Conversiones entre clases base y clases

derivadas.

(8)

• Las acciones de las funciones definidas en la clase base pueden ser redefinidas en las clases derivadas.

• Ejemplo: vamos a crear una clase derivada de ‘Coche’ llamada ‘Camion’, en la que almacenaremos también el peso del trailer.

class Camion:public Coche {

public:

Camion();

Camion(int peso, int vel, const string &n, int peso_trailer);

4. Redefinición de funciones miembros 4. Redefinición de funciones miembros 4. Redefinición de funciones miembros 4. Redefinición de funciones miembros

Tema 6: Herencia Camion(int peso, int vel, const string &n, int peso_trailer);

void setPeso(int peso, int peso_trailer);

int getPeso() const;

protected:

int peso_remolque;

}

int Camion:: getPeso() const {

int peso_total;

peso_total= Coche::getPeso() + peso_remolque;

return(peso_total);

}

Para llamar a getPeso de la clase Coche hay que hacer uso de “::”

Creamos un nuevo método getPeso, que actuará

de forma distinta en esta clase.

15

1. Herencia.

2. Miembros protegidos.

3. El constructor de la clase derivada.

Índice Índice Índice Índice

4. Redefinición de funciones miembro.

5.

5.

5.

5. Herencia múltiple Herencia múltiple Herencia múltiple Herencia múltiple.

6. Conversiones entre clases base y clases

derivadas.

(9)

• Hemos visto que una clase puede derivar de otra clase base.

• C++ permite también la herencia múltiple: una clase deriva de varias clases base, y por tanto hereda las funcionalidades de todas ellas.

• Ej: clase Motor que almacena información del motor (potencia, etc.)

class Motor { public:

Motor();

Motor(const string &nr_serie, int pot,

5. Herencia múltiple 5. Herencia múltiple 5. Herencia múltiple 5. Herencia múltiple

Motor(const string &nr_serie, int pot, const string &tipo_combus);

//Interfaz

void setNumSerie(const string &num_serie);

string getNumSerie() const;

void setPotencia(int pot);

int getPotencia() const;

void setTipoCombus(const string &tipo);

string getTipoCombus() const;

private:

string numSerie, tipoCombus;

int potencia;

};

17

• Para representar un automóvil que tenga las propiedades de la clase Coche, y las de la clase Motor podemos utilizar derivación múltiple.

class CocheMotor: public Coche, public Motor {

public:

CocheMotor();

Coche Motor( int p, int v, const string &nom, const string &serie, int pot, const string &combus);

};

CocheMotor::CocheMotor (int p, int v, const string &nom, const string &serie, int pot, const string &combus)

5. Herencia múltiple 5. Herencia múltiple 5. Herencia múltiple 5. Herencia múltiple

const string &serie, int pot, const string &combus) : Coche(p, v, nom), Motor(serie, pot, combus) {

}

• La palabra public delante de Coche y de Motor, es necesaria, porque la derivación en C++, por defecto es privada.

• La derivación múltiple para formar la clase CocheMotor no añade

funcionalidad, únicamente combina dos clases pre-existentes. Esto será muy útil para desarrollar clases a partir de otras más pequeñas.

• El constructor que espera seis argumentos no contiene código, el único propósito de éste es llamar a los constructores de las clases base.

Mismo orden en que ha sido derivada

18

(10)

1. Herencia.

2. Miembros protegidos....

3. El constructor de la clase derivada.

Índice Índice Índice Índice

Tema 6: Herencia 19

4. Redefinición de funciones miembro.

5. Herencia múltiple.

6. 6.

6. 6. Conversiones entre clases base y clases Conversiones entre clases base y clases Conversiones entre clases base y clases Conversiones entre clases base y clases derivadas.

derivadas.

derivadas.

derivadas.

• Cuando utilizamos herencia al definir una clase, podemos decir que un objeto de la clase derivada sea al mismo tiempo un objeto de la clase base.

• Esto tiene algunas consecuencias:

• Conversiones en la asignación de objetos:

• Si definimos dos objetos, uno de clase base y otro de la derivada:

Vehiculo v(900); //Vehículo con peso 900

Coche a(1200,130,”Ford”); //peso=1200, vel=130 y marca Ford

6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada

Coche a(1200,130,”Ford”); //peso=1200, vel=130 y marca Ford

Como Coche es a su vez un Vehiculo podríamos hacer la asignación:

v=a; // El objeto v guardará el valor 1200 en su atributo peso

También podríamos intentar:

a=v; // El objeto a recibiría el peso, pero no la velocidad ni el nombre.

// Esta asignación NO será aceptada por el compilador.

• Regla: cuando se asignan objetos relaciones, una asignación en la que

sobran parámetros es legal, pero no es legal si hay parámetro en blanco a la

izquierda.

(11)

• La conversión de un objeto de la clase base a uno de la clase derivada puede ser definida explícitamente si se necesita.

Creamos en la clase Coche, una función asignación que acepte como parámetro un objeto Vehiculo:

const Coche & Coche::operator=(const Vehiculo &veh) { setPeso(veh.setPeso());

...

}

6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada

Tema 6: Herencia }

• Conversión en la asignación de punteros.

• Cuando llamamos a una función utilizando un puntero a un objeto, el tipo de puntero determina qué funciones miembro están disponibles.

Camion c;

Vehiculo *vp;

vp = &c;

....

float a = vp->getPeso();

Esto es válido, pero al llamar a la función getPeso(), estaremos llamando a la función de la clase Vehiculo.

21

• Problema: En el anterior ejemplo, la función getPeso() invocada será la de Vehiculo y el valor devuelto no será el correcto.

• También podemos hacer una conversión explícita:

Camion cam;

Vehiculo *vp;

vp = &cam;

...

vp apunta a un objeto Camion

6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada 6. Conversión entre clases base y derivada

Tema 6: Herencia ...

Camion *cam2;

cam2 = (Camion *) vp;

convierte una variable Vehiculo* en una Camion* . Esto funcionará correctamente si en vp realmente apunta a un objeto Camion

22

Referencias

Documento similar

Luis Miguel Utrera Navarrete ha presentado la relación de Bienes y Actividades siguientes para la legislatura de 2015-2019, según constan inscritos en el

La campaña ha consistido en la revisión del etiquetado e instrucciones de uso de todos los ter- mómetros digitales comunicados, así como de la documentación técnica adicional de

You may wish to take a note of your Organisation ID, which, in addition to the organisation name, can be used to search for an organisation you will need to affiliate with when you

Where possible, the EU IG and more specifically the data fields and associated business rules present in Chapter 2 –Data elements for the electronic submission of information

The 'On-boarding of users to Substance, Product, Organisation and Referentials (SPOR) data services' document must be considered the reference guidance, as this document includes the

In medicinal products containing more than one manufactured item (e.g., contraceptive having different strengths and fixed dose combination as part of the same medicinal

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in