Está en la página 1de 7

Introduccin

Se pueden definir jerarquas de clases, con


Herencia y Polimorfismo clases generales que definen el
comportamiento comn a unos objetos y
clases especficas que slo aaden o
redefinen el comportamiento propio, nico,
de ese objeto respecto a la clase general.
Clases bases y clases derivadas.

Curso de programacin de C/C++ 57 Curso de programacin de C/C++ 58

Ejemplos (I) Ejemplos (II)


Clase Persona (fecha nac., DNI, dir., tel.)
Clase Vehculos: Peso, Potencia, Cilindrada
Jefe (despacho, incentivos, ...)
Coches: N puertas, extras
Vendedor (rea, clientes,...) Monovolmenes
Secretarios Deportivos.
Clase Forma: rea (?), permetro (?), color Furgonetas
Rectngulo: dos lados, rea, permetro. Camiones: PMA, Tara, N ejes.
Cuadrado: un lado, rea, permetro. Rgidos
Con remolque
Elipse: dos radios, rea
Circulo: Un radio, rea, circunferencia Motocicletas.
Con matrcula
Clasificacin Animales (es un ..) Sin matrcula
Curso de programacin de C/C++ 59 Curso de programacin de C/C++ 60

Control de Acceso Herencia


Hay tres posibilidades respecto a la Base: Se hereda todo, atributos y mtodos.
Private: Solo se usan en la clase en cuestin. Con las restricciones de acceso comentadas.
Protected: Se usan en esa clase y sus hijas. Si un mtodo cambia su comportamiento
Public: Se puede usar fuera de la clase. puede redefinirse. Puede invocar al padre:
cuadrado::imprimir () {
Se aplica el ms restrictivo entre el definido
forma::imprimir();
en la clase base y el de acceso a la misma.
cout << con lado << lado;
Ej: class derivada: public base { ... } Si no se redefine usa el mtodo del padre.
Curso de programacin de C/C++ 61 Curso de programacin de C/C++ 62

1
Sustitucin de mtodos Herencia Mltiple
class D: public B { };
Clase D puede reutilizar, extender o crear su
Hereda de varias clases a la vez.
propia definicin de mtodo M de B
cuad: public rect, public poly
Para sustituir la implementacin de M de B, {... };
lo define de nuevo Es complejo y ambiguo. Un mtodo puede
Si lo extiende, estar definido en varias clases padre.
desde M de D puede invocar M de B Luego lo ampliaremos, aunque debe evitarse.
Pero usando el operador de mbito B::M
Si desea reutilizarlo no debe hacer nada.
Curso de programacin de C/C++ 63 Curso de programacin de C/C++ 64

Constructores y Destructores Constructor de la clase derivada


class D: public B { };
Los objetos se construyen de ms general a En la lista de iniciacin del constructor de la clase D
Invoca constructor B antes que los de miembros de datos de D
menos y se destruyen de forma inversa. (m1,...)
Sino podra faltar informacin necesaria. Al fin y al cabo, un objeto D esconde a un objeto B. Primero
se construye B y luego D
Si tienen parmetros se le pasan:
cuad::cuad(lado l) :
D(args. constructor de D) : B(args. constructor de B), m1(...), ... {};
rect(l, l), poly(4)
{... };

Curso de programacin de C/C++ 65 Curso de programacin de C/C++ 66

Un D es un B, pero un B no es un D Un D es un B, pero un B no es un D
Las aplicaciones trabajan con B, D1, D2, ... Trabajando con punteros o referencias a objetos
Comportamiento cambia si se usan punteros o no B *pB = &objB; // OK; trivial
Trabajando directamente con objetos D *pD = &objD; // OK; trivial
Asignar objeto B a D da error de compilacin D *pD = &objB; // error de compilacin: B no es D
objeto B no es D B *pB = &objD; // OK: objeto D es de la clase B
Asignar objeto D a B OK pero se produce slicing Otro ejemplo de uso de punteros a objetos
En la copia se pierde toda la info. del objeto asociada a
clase D B *pB = &objD;
En la mayora de los casos, no es lo que pretenda el D *pD = pB; // error de compilacin, pero correcto
programador // uso de dynamic_cast

Curso de programacin de C/C++ 67 Curso de programacin de C/C++ 68

2
Invocacin de mtodos Invocacin de mtodos
B tiene mtodos M1 y M2 B *pX = &objD;
D derivada de B redefine/sustituye M2 Comportamiento extrao: pX->M2(...) debera
Ejemplos de invocacin a travs de punteros: ejecutar M2 de D
D *pD = &objD; B *pB = &objB; B *pX = &objD; Resultado de invocar mtodo depende de puntero
pD->M1(...); // M1 de B Si lista de punteros a B que contiene objetos
pD->M2(...); // M2 de D; CASO 1 derivados de B: D1,D2...
pB->M1(...); // M1 de B Comportamiento razonable: ejecuta M2 de derivado
pB->M2(...); // M2 de B polimorfismo
pX->M1(...); // M1 de B
pX->M2(...); // M2 de B; CASO 2CASO1 SORPRESA?
Curso de programacin de C/C++ 69 Curso de programacin de C/C++ 70

Polimorfismo (I) Polimorfismo (II)


Hay que tener presente que un director es La idea del polimorfismo es tratar de la
un empleado, pero no a la inversa: misma manera objetos distintos.
Empleado Pepe; if (Fin de Ao)
Director D;
for (int i=0; i < n; i++)
Pepe = D; // Bien
vect_empleados[i].incr_salario();
D = Pepe; // Mal
//Directores un 20%, otros un 10%
Pero que pasa si tenemos un vector de
empleados y no queremos que pierdan su
comportamiento (vendedor, jefe, contable)?
Curso de programacin de C/C++ 71 Curso de programacin de C/C++ 72

Mtodos Virtuales Mtodos virtuales


Esto se consigue con los Mtodos Virtuales.
Clase polimrfica: al menos un mtodo M virtual
Se define un vector de personas, pero a la hora de Invocacin a M mediante puntero (B *b) se
acceder a cada una de ellas se comportan segn lo resuelve en ejecucin
que sea: Polimorfismo. Ligadura dinmica (dynamic binding)
Funciona slo con Punteros y Referencias. Si redefinida en clase del objeto (D), usa esa versin
Cada clase tiene estos mtodos redefinidos y en Sino la de la clase base directa de D, si la hay, y as hasta B
ejecucin se mira el tipo del objeto y se invoca al Con polimorfismo mismo comportamiento bM y dM (D *d)
mtodo correspondiente. dM se comporta igual sea M polimrfico o no
Delante del mtodo se pone virtual. Invocacin con operador de mbito no es polimrfica (bB::M)
Si una clase no lo redefine, se sube en la jerarqua
hasta encontrar la definicin.
Curso de programacin de C/C++ 73 Curso de programacin de C/C++ 74

3
Destructores Virtuales Destructores virtuales
Necesidad de incluir destructor virtual en clase base
Los destructores pueden ser virtuales polimrfica: virtual ~C() { }
virtual ~forma(); Incluso aunque clase B no tenga nada que destruir
Puede (o podr) haber clases derivadas que tengan que hacerlo
Ejemplo en que es necesario:
forma * lista[MAX]; Si no destructor virtual, problema al destruir objeto
lista[0] = new rectangulo(); mediante B*
lista[1] = new circulo(); Se invoca el destructor de B en vez del destructor de D
.... Los constructores no pueden ser virtuales
for (i=0; i<MAX; i++)
Si se necesita una funcionalidad de ese tipo hay que programarla
delete lista[i];
Constructores virtuales

Curso de programacin de C/C++ 75 Curso de programacin de C/C++ 76

Polimorfismo vs plantillas Clases abstractas


Capacidad de tratar uniformemente objetos de
distintas clases
Si en cierto nivel de la jerarqua no tiene
Incluso nuevas clases futuras
sentido se usan funciones virtuales Puras:
Plantillas proporcionan polimorfismo esttico virtual void forma::area() = 0;
En compilacin se decide destino de llamada a funcin
Estas clases son abstractas y no pueden
Polimorfismo dinmico: instanciarse. Las clases derivadas debern
Determinar en tiempo de ejecucin destino de llamada implementar obligatoriamente todas estas
a funcin funciones, sino son clases abstractas tambin
Curso de programacin de C/C++ 77 Curso de programacin de C/C++ 78

Clases abstractas
A menudo, no tiene sentido crear objetos de una Clases Abstractas
cierta clase base: Clase Abstracta
Ejemplo
La clase no est concebida como un molde para crear forma F; //NO.
objetos, es un contenedor de funcionalidad comn forma *F; //SI
Clase abstracta: tiene funciones virtuales puras Las referencias tambin son vlidas.
virtual void imprimir() = 0; func(forma &F)
Derivada debe implementar todas las FVPs {F.area(); //SI}
Main() {
Sino ser tambin abstracta
cuadrado cuad;
Clase abstracta con slo FVPs define una interfaz func(cuad);...
Clases derivadas slo heredan interfaz
Curso de programacin de C/C++ 79 Curso de programacin de C/C++ 80

4
Tipos de herencia Tipos de herencia
Segn el grado de funcionalidad que se hereda
Reutilizacin de cdigo Herencia de la implementacin
Tambin se puede lograr mediante composicin Ms orientada hacia la reutilizacin
En vez de D es un B, D contiene un miembro de datos B Herencia de la interfaz
Aspecto con cierta polmica: Mejor como atributos Ms orientada hacia el polimorfismo

Polimorfismo: Tratamiento uniforme de Segn la cardinalidad de la herencia


diversos objetos Simple: Clase slo puede derivar de una clase base
Mismo cdigo maneja distintos tipos de clases Mltiple: Clase puede derivar de mltiples clases
Incluso nuevas clases que no existan cuando se program base

Curso de programacin de C/C++ 81 Curso de programacin de C/C++ 82

Control de acceso:
Tipos de herencia Recapitulacin funciones miembro
Lenguaje C++:
No distingue entre herencia de implementacin y de
Clase B Abstracta con funciones miembro
interfaz. Debe hacerlo el programador M1(FNV), M2 (FV) y M3 (FVP)
Proporciona herencia mltiple pB (tipo B*) apunta a objeto de clase D
Java Accin asociada a pBMX():
Distingue entre herencia de implementacin y de M1 no sustituido por D: Invoca M1 de B
interfaz M1 sustituido por D: Invoca M1 de B
Provee herencia simple de implementacin y M2 no sustituido por D: Invoca M2 de B
mltiple de interfaz M2 sustituido por D: Invoca M2 de D
M3 no sustituido por D: No factible
M3 sustituido por D: Invoca M3 de D
Curso de programacin de C/C++ 83 Curso de programacin de C/C++ 84

Herencia pblica Herencia privada


class D: public B { }; class D: private B {}; // por defecto (si se omite)
D puede acceder a miembros pblicos y protegidos de B
D puede acceder a m. pblicos y protegidos de B
No a privados
No a privados
Recuerde: usuario de B slo a miembros pblicos
Recuerde: usuario de B slo a miembros pblicos
Usuario de D puede acceder a miembros pblicos de D y B
La interfaz de D incluye directamente la de B Pero usuario de D no puede acceder a m. pblicos
Clases derivadas de D: de D y B
Pueden acceder a miembros pblicos y protegidos de D La interfaz de D no incluye la de B
y de B
Es como si B fuera un miembro de datos pblico de D

Curso de programacin de C/C++ 85 Curso de programacin de C/C++ 86

5
Herencia privada
Derivadas de D no pueden acceder ni a mtodos
Herencia protegida
pblicos de B class D: protected B { };
Es como si B fuera un miembro de datos Igual que privada pero:
privado de D Derivadas de D pueden acceder a m. pblicos y
D no es un B, D est implementado basndose protegidos de B
en B Es como si B fuera un miembro de datos
Similar a composicin protegido de D
No hay polimorfismo para usuarios de clase B y
derivadas:
B* pB = &objD; // Error

Curso de programacin de C/C++ 87 Curso de programacin de C/C++ 88

Uso de herencia Uso de herencia


Pblica: hereda interfaz, til para polimorfismo Ventaja privada frente a herencia pblica:
Usuarios de D no se ven afectados por cambios en
Privada: herencia de implementacin no interfaz
interfaz de B
Adecuada para reutilizacin de cdigo
Pero no para polimorfismo
Desventaja privada frente a herencia pblica:
Similar a composicin (incluir un campo privado B en Si usuario de D requiere acceso a funcionalidad
vez de derivar) pblica de B
Hay que incluir una funcin pblica pasarela en D
Protegida: mismo uso que herencia privada
pero si se prev que:
Clases derivadas de D puedan necesitar acceder a B
Curso de programacin de C/C++ 89 Curso de programacin de C/C++ 90

Herencia mltiple Herencia mltiple


class D: public B1, public B2, private B3, protected B4 { }; Si bases abstractas, D debe completarlas para ser
D(args.constr.D): B1(args.constr.B1), B2(args.constr.B2), ..., concreto
M1(...), ... {}; Posible colisin entre nombres de miembros
pblicos de clases base
D es un B1 y un B2 Uso de operador de mbito para resolver ambigedad
B1 *pB1 = &objD; // OK d.B1::M();
B2 *pB2 = &objD; // OK d.B2::M();
Usuarios D acceso directo a miembros de B1
(MB1) y B2 (MB2)
d.MB1(); d.MB2(); // OK
Curso de programacin de C/C++ 91 Curso de programacin de C/C++ 92

6
Clases bases replicadas Clase base virtual
class D1: public B {...}; Pero en otros caso no: Empleado (B)
incluye nombre y apellidos
class D2: public B {...};
Ayudante (D1), Temporal (D2),
class DD: public D1, public D2 {...}; AyudanteTemporal (DD)
No queremos que aparezcan 2 veces los B
B B
La clase B est duplicada en clase DD nombres y apellidos
Si tiene un miembro de datos privado, Herencia virtual D1 D2
D1 D2
aparecer 2 veces class D1: public virtual B {...};
En algunos casos es lo que se pretende class D2: public virtual B {...};
DD DD
class DD: public D1, public D2 {...};
Curso de programacin de C/C++ 93 Curso de programacin de C/C++ 94

Operadores dynamic_cast y typeid Operadores dynamic_cast y typeid


C++ guarda info. en t. de ejecucin sobre clases La conversin ser vlida si tipo de objeto real es
polimrficas C o derivado de C. Sino devuelve 0
Run-Time Type Information Slo para punteros a clases polimrficas
Compilador no sabe tipo de objeto apuntado por Uso en el ejemplo:
puntero a base: B *pB = &objD; D *pD = dynamic_cast<D *>(pB);
B *pB = &objD; D *pD = pB; // error de compilacin, typeid: informacin de un tipo dado el mismo o
// pero es correcto
una expresin
dynamic_cast pide conversin a puntero de clase C Devuelve un type_info que incluye mtodo name:
cout << typeid(*pB).name() <<endl;
Curso de programacin de C/C++ 95 Curso de programacin de C/C++ 96

Consejos sobre diseo


Sobrecarga y Sustitucin de mtodos de jerarqua de clases
rbol estrecho y profundo
La sobrecarga y la sustitucin no se llevan bien Clases intermedias abstractas; clases finales concretas
En B hay dos versiones de M (p. ej. con argumento Minimizar herencia mltiple de implementacin
int y string)
Explotar herencia mltiple de interfaces (pseudo Java)
D sustituye el mtodo M para el string
Clases abstractas sin implementacin
Usuario de D invoca M con un entero ERROR Una clase puede necesitar:
Solucin: declaracin using en parte pblica de D: Herencia de implementacin (Reutilizacin)
using B::M; Uso de herencia privada/protegida (o composicin)
Reutilizacin: Herencia de interfaz (polimorfismo)
Uso de herencia pblica de interfaces
Curso de programacin de C/C++ 97 Curso de programacin de C/C++ 98

También podría gustarte