Sunteți pe pagina 1din 9

Herencia

Herencia: Sintaxis

Junto con el polimorfismo, es la caracterstica ms importante de la POO. Permite reutilizar cdigo, definiendo nuevas clases a partir de otras ya existentes. Si una clase A hereda de otra clase B, a B la llamaremos clase base, mientras que A ser una subclase de B. Si una clase hereda de otra, en particular hereda todos sus mtodos y atributos, pudiendo adems declarar y definir ms atributos y mtodos, y redefinir algunos de los mtodos heredados.
1

Sintaxis: class B : Identificador A {....};

indica que la clase B hereda de la clase A. El Identificador especifica el tipo de herencia, que en C++ puede ser: pblica, protegida y privada.

usaremos la pblica:

No vamos a utilizar ni la herencia protegida ni la privada. Slo

class B : public A {....};

Herencia: Sintaxis

Herencia: Niveles de proteccin


En la implementacin de la clase B podemos utilizar todos los atributos pblicos y protegidos (protected) de la clase A, pero nunca los privados. El nuevo identificador protected para mtodos y atributos indica que estos pueden ser utilizados dentro de la implementacin de una clase que herede de ella. En cualquier otra situacin se comportan como atributos privados.

OJO:

Si no se pone ningn identificador se asume que la herencia es privada.

Herencia: Niveles de proteccin


Identificador de mtodo o atributo Accesible desde la propia clase? Accesible desde subclases? Accesible para los dems?

Herencia: Un ejemplo
class Base { private: // no accesible desde las subclases int x,y; protected: // accesible desde las subclases int nx,ny; public: // accesible para todos Base():x(0),y(0),nx(0),ny(0){}; Base(int a,int b):x(a),y(b),nx(0),ny(0){};
Lista de inicializaciones

public

SI SI SI

SI NO SI

SI NO NO

private

protected

Herencia: Un ejemplo
void set(int a,int b,int c,int d) {x=a;y=b;nx=c;ny=d;} int getX(){return x;} mtodos inline int getY(){return y;} int getNX(){return nx;} int getNY(){return ny;} };

Herencia: Un ejemplo
class Hija:public Base{ private: int p1,p2; public: void actualizaNXNY(){ p1=nx; // CORRECTO p2=y+ny; // INCORRECTO set(2,3,p1,p2); // CORRECTO }; void actualizaXY(){ p1=getX(); p2=getY();}; // CORRECTO int getP1(){return p1;} int getP2(){return p2;};
7 8

Herencia: Constructoras

Herencia: Constructoras

Supongamos que declaramos la variable: Hija h; Qu constructora se ejecuta?

Si aadimos a la clase Hija: Hija(){set(1,1,1,1);p1=5;p2=7;} se ejecutarn:

La constructora por defecto de la clase Hija, ya que, como la clase Hija no tiene definida ninguna constructora, tiene una por defecto, que lo nico que hace es invocar a la constructora por defecto de la clase Base.

La constructora sin argumentos de la clase Base. La constructora sin argumentos de la clase Hija.

10

Herencia: Constructoras

Herencia: Constructoras
Hija(int a,int b):Base(a,b),p1(a+2),p2(b+2){}; Llamada explcita a la constructora con dos argumentos de la clase Base. Hija(int a,int b):p1(a+2),p2(b+2){}; Como no aparece llamada explcita, se llama a la constructora por defecto de la clase Base.

Cuando se crea un objeto de una subclase, siempre se invoca en primer lugar (implcita o explcitamente) a una constructora de la clase base. Explcitamente: mediante la lista de inicializaciones en las constructoras de la subclase. Implcitamente: Si no se especifica una, se ejecuta la constructora por defecto de la clase base.

11

12

Herencia: Destructoras

Herencia: Redefinicin de mtodos


Una subclase puede redefinir mtodos de la clase base:
clase Base { ..... int suma(){ ShowMessage(Clase Base); return nx+ny+x+y;} } clase Hija: public Base { ...... int suma(){ ShowMessage(Clase Hija); return px+py;} }
13 14

Para el caso de las destructoras, cuando se destruye un objeto de una subclase, se invoca primero a la destructora de la subclase y al final se invoca a la destructora de la clase base.

Herencia: Redefinicin de mtodos

Herencia: Casting

Cmo funciona? Enlace esttico, el de la clase declarada para la variable (se decide en tiempo de compilacin). Hija h(2,3); ShowMessage(h.suma()); Clase Hija

Qu hacer si queremos que h ejecute el mtodo suma de la clase Base? // casting hacia arriba ShowMessage(((Base) h).suma());

Es correcto: ? b=h; // POLIMORFISMO b.suma(); Qu pasa con los atributos p1 y p2 que no tiene b? Qu mtodo se ejecuta? El de la clase Base

Base b(2,3); ShowMessage(b.suma()); Clase Base

15

16

Herencia: Enlace esttico

Herencia: Enlace dinmico

Enlace esttico (i.e. en tiempo de compilacin). Se ejecutan los mtodos de la clase a la que pertenece la variable declarada y no del posible objeto que contiene.
Es correcto? ShowMessage((Hija b).suma()) h=b; h.suma(); NO: Error de compilacin. b no tiene los atributos p1 y p2 de la clase Hija !!!

Para conseguir que se ejecutara el mtodo suma de la clase Hija (objeto contenido en la variable b) necesitaramos mtodos virtuales con enlace dinmico (i.e. en tiempo de ejecucin), que slo tienen sentido en presencia de punteros y referencias). clase Base { ....... virtual int suma(){....} }; Hija h(2,3); Base* b = &h;
ShowMessage(b->suma()); // enlace dinmico

17

18

Herencia: Enlace dinmico


Conclusin: Utilizaremos el polimorfismo con PUNTEROS. Observacin: Si en la clase Hija quisiramos utilizar el mtodo suma de la clase Base, debemos utilizar la notacin: Base::suma() class Hija:public Base{ ......... virtual int suma(){ ShowMessage("Clase hija"); return Base::suma()+p1+p2;} };
19

Polimorfismo
Permite disear e implementar sistemas que sean extensibles con gran facilidad. Los programas se escriben para que procesen objetos en forma genrica: objetos de todas las clases existentes en una jerarqua.

A B C D

20

Polimorfismo

Polimorfismo y mtodos virtuales

Una variable de tipo A puede contener a cualquier objeto de sus subclases (no al contrario). A=animales; B=perros; C=gatos; D=leones;

Supongamos que la clase A contiene un mtodo esttico p, y que las subclases de A redefinen dicho mtodo: C* objC = new C(); B* objB = new B(); A* objA = objB; objA->p(); // (1) objA = objC; objA->p(); // (2)

Tiene sentido:

Un perro es un animal? SI A* a = new B();

// CORRECTO

Todos los animales son perros? NO B* b = new A();

// INCORRECTO
21 22

Polimorfismo y mtodos virtuales

Polimorfismo y mtodos virtuales

Tanto en (1) como en (2) se ejecuta el mtodo p de la clase A. La razn es que objA es de tipo A, y como el mtodo es de enlace esttico, siempre se ejecuta el mtodo de la clase a la que pertenece la variable y no el de la clase del objeto contenido en la variable (enlace dinmico-tiempo de ejecucin). qu podramos hacer para que se ejecute el mtodo del tipo del objeto contenido en la variable? mtodos virtuales Se determina el mtodo a ejecutar en tiempo de ejecucin ENLACE DINMICO (SLO POSIBLE CON PUNTEROS Y REFERENCIAS)
23

Sintaxis: virtual tipo nombreMetodo(argumentos);

Convenio: Poner virtual, adems de en la clase base, en todas las subclases directas o indirectas que redefinan el mtodo.

24

Polimorfismo y mtodos virtuales: Un ejemplo


class Base { public: virtual void p(){ShowMessage(Clase base");} };

Polimorfismo y mtodos virtuales: Un ejemplo

Base Base* b=new Hija(); b->p(); // p de la clase Hija Hija* h = new Nieta(); h->p(); // p de la clase Nieta

class Hija:public Base { public: Hija virtual void p(){ShowMessage(Clase hija");} }; class Nieta:public Hija { Nieta public: virtual void p(){ShowMessage(Clase nieta");} };

Aunque en las subclases el mtodo p no apareciera como virtual lo sera igualmente.

25

26

Polimorfismo y mtodos nuevos

Polimorfismo: Destructoras
class Base{ private: T* t; // objeto dinmico de la clase T public: Base(){t=new T(...);....} ..... ~Base(){delete t; t=NULL;}

Cuando una subclase aade nuevos mtodos, si hacemos uso del polimorfismo, no podemos invocarlos directamente: hay que hacer casting. class Base { public: virtual void p(){ShowMessage(Clase base");}}; class Hija:public Base { public: virtual void p(){ShowMessage(Clase hija");} void p1(){ShowMessage(Soy nuevo);}};

Base * b = new Hija(); b->p1(); // error de compilacin (Hija* b)->p1(); // se ejecuta el mtodo p1 de la clase Hija
27 28

Polimorfismo: Destructoras
class Hija:public Base { private: M* m; // objeto dinmico de la clase M public: Hija():Base(){m=new M(...);...} ..... ~Hija(){delete m; m=NULL;} };
29

Polimorfismo: Destructoras
Base* b = new Hija(); delete b;

Se invoca a la destructora de la clase Base !!! Nos dejamos sin borrar m !!! SOLUCIN: La destructora de la clase Base debe ser virtual. En tal caso, primero se ejecutar la destructora de la clase Hija, y despus la de la clase Base.

30

Polimorfismo: Clases abstractas

Polimorfismo: Clases abstractas


Por ejemplo: class Base { public: virtual void show()=0; };

Una clase abstracta es una clase de la que no podemos tener instancias (i.e. objetos). Se usan como clases tipo de las cuales heredan otras clases. Para indicar que una clase es abstracta basta introducir un mtodo virtual puro (o abstracto). virtual tipo nombreMetodo(argumentos)=0;

Una clase que herede de la clase Base debe implementar el mtodo show. En otro caso la subclase tambin se considerar abstracta.
32

31

Informacin de tipo en ejecucin


Informacin de tipo en ejecucin


Ejemplos: Grafico* graf = new Rectangulo(......); if typeid(*graf)==typeid(Rectangulo) ShowMessage(cierto); else ShowMessage(falso);

La funcin typeid devuelve una referencia a un objeto de la clase type_info. Los objetos de esta clase representan un tipo. Sintaxis: typeid(expresin) == typeid(tipo)

Si la clase Grafico contiene al menos un mtodo virtual (clase polimrfica), se mostrar cierto, en otro caso se mostrar falso. Con clases polimrficas, typeid(*graf) devuelve el tipo del objeto apuntado por graf en tiempo de ejecucin. En otro caso devuelve el tipo en tiempo de compilacin.
34

33

Informacin de tipo en ejecucin

La clase type_info tiene definidos los operadores == y != Para utilizar typeid es necesario incluir el mdulo typeinfo: #include <typeinfo>

typeid(*a) con a == NULL genera una excepcin.

35

S-ar putea să vă placă și