Documente Academic
Documente Profesional
Documente Cultură
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
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:
Herencia: Sintaxis
OJO:
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
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
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: 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
15
16
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
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
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:
// CORRECTO
// INCORRECTO
21 22
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
Convenio: Poner virtual, adems de en la clase base, en todas las subclases directas o indirectas que redefinan el mtodo.
24
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");} };
25
26
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
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
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
La clase type_info tiene definidos los operadores == y != Para utilizar typeid es necesario incluir el mdulo typeinfo: #include <typeinfo>
35