Herencia Introducción a la herencia

Anuncio
Programación en C++
Herencia
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 1
Programación en C++
Introducción a la herencia
•
•
•
La herencia consiste en crear nuevas clases mediante la
modificación de clases que ya existen:
– Se heredan las variables miembros y las funciones miembro definidas.
– Se pueden incorporar nuevas variables miembro o nuevas funciones
miembro.
– Se pueden redefinir o sobrecargar las variables y funciones miembro
ya existentes.
– Es un tipo de la clase ...
Es un método alternativo a la definición de nuevas clases
mediante la inclusión de clases ya definidas.
– Es una clase independiente dentro de otra clase
– Forma parte de la clase ...
Clase base, clase hija (o clase derivada)
– Las clases hijas añaden más información a la clase base.
– Las clases base son más genéricas.
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 2
Programación en C++
Ejemplo de herencia
•
•
•
•
Clase base de obstáculos
(CObstaculo) que es una
abstracción del concepto
obstáculo.
Clases derivadas:
– CSegmento: obstáculos con
forma de segmento.
– CCirculo:obstáculo con forma de
círculo.
CObstaculo
CSegmento
CCirculo
Aunque son obstáculos, la
forma de procesarlos, es
diferente
Las clases hijas pueden
acceder a la parte privada y
protegida de la clase base
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 3
Programación en C++
Implantación del ejemplo de los obstáculos (I)
class CObstaculo
Ejemplo de clase base de obstáculos
{
private:
double m_opacidad;
protected:
std::string m_sMensaje;
public:
~CObstaculo(){};
// constructores
CObstaculo(){ m_opacidad = 0; m_sMensaje = "Soy un obstaculo:";}
CObstaculo(double opacidad)
{m_opacidad = opacidad; m_sMensaje = "Soy un obstaculo:";};
void Identificacion(ostream& o)
{ o << m_sMensaje.c_str() << endl;};
};
Prof. Álvaro Sánchez Miralles
Se identifica
UPCO ICAI Departamento de Electrónica y Automática 4
Programación en C++
Implantación del ejemplo de los obstáculos (II)
class CSegmento : public CObstaculo
Características del segmento
{
private:
CPunto m_p1, m_p2; // punto inicial y final del segmento
double m_longitud, m_pendiente; // en grados -179 hasta 180
void Segmento(CPunto p1,CPunto p2);
void Segmento(CPunto p1, double longitud, double pendiente);
public:
~CSegmento(){};
Información del constructor que
// constructores
debe usar de la base
CSegmento(){};
CSegmento(double opacidad):CObstaculo(opacidad){};
CSegmento(const CSegmento& r){*this=r;};
CSegmento(CPunto& p1, CPunto& p2){Segmento(p1,p2);};
CSegmento(CPunto& p1, double longitud, double pendiente)
{Segmento(p1,longitud,pendiente);};
Acceso a la parte protegida
de la base
CSegmento& operator=(const CSegmento& r);
void Identificacion(ostream& o)
{ m_sMensaje = "Soy un segmento:";
CObstaculo::Identificacion(o);};
};
Prof. Álvaro Sánchez Miralles
que se de
use
la función
de la base,
UPCO ICAIDice
Departamento
Electrónica
y Automática
5
no la propia del segmento
Programación en C++
Implantación del ejemplo de los obstáculos (III)
class CCirculo: public CObstaculo
{
private:
CPunto m_p1; // centro del círculo
double m_diametro; // diámetro del circulo
void Circulo(CPunto p1,double diametro)
{m_p1 = p1; m_diametro = diametro;};
public:
~CCirculo(){};
// constructores
CCirculo(){};
CCirculo(double opacidad):CObstaculo(opacidad){};
CCirculo(const CCirculo& c){*this = c;};
CCirculo(CPunto p1,double diametro) { Circulo(p1,diametro);}
CCirculo& operator=(const CCirculo& c);
void Identificacion(ostream& o)
{ m_sMensaje = "Soy un círculo:";
CObstaculo::Identificacion(o);};
};
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 6
Programación en C++
Prueba del ejemplo con obstáculos
#include <list>
La lista es:
Soy un obstaculo:
Soy un obstaculo:
using namespace std;
int main(int argc, char* argv[])
{
list<CObstaculo> lo;
list<CObstaculo>::iterator ilo;
CPunto p(1,1);
CSegmento r(p,2,0);
CCirculo c(p,2);
// rellena la lista con obstáculos
lo.push_back(r);
lo.push_back(c);
// recorre la lista de obstáculos
ilo=lo.begin();
cout << "La lista es: " << endl;
for (int i = 0; i < lo.size() ; i++, ilo++)
ilo->Identificacion (cout);
¿Pero no era un segmento
y un círculo?
return 0;
}
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 7
Programación en C++
Funciones virtuales
•
•
Es el principal mecanismo que tiene C++ para permitir
polimorfismo
– Si una clase hija sobrecarga una función virtual de su clase padre,
entonces siempre que un objeto de la clase padre, que provenga
de otro objeto de la clase hijo, vaya a usar esa función usará la
función del hijo.
– Es decir, el compilador garantiza una perfecta correspondencia
entre objetos y las funciones virtuales que les corresponden.
Una función miembro se declara virtual con el modificador
virtual.
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 8
Programación en C++
Ejemplo de obstáculos con funciones virtuales
class CObstaculo
{
...
virtual void Identificacion(ostream& o)
{ o << m_sMensaje.c_str() << endl;};
};
class CCirculo: public CObstaculo
{
...
void Identificacion(ostream& o)
{ m_sMensaje = "Soy un círculo:";
CObstaculo::Identificacion(o);};
};
class CCirculo: public CObstaculo
{
...
void Identificacion(ostream& o)
{ m_sMensaje = "Soy un círculo:";
CObstaculo::Identificacion(o);};
};
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 9
Programación en C++
Prueba ejemplo de funciones virtuales
#include <list>
using namespace std;
La lista es:
Soy un segmento:
Soy un círculo:
int main(int argc, char* argv[])
{
list<CObstaculo*> lo;
El polimorfismo funciona sólo a
list<CObstaculo*>::iterator ilo;
nivel de punteros
CPunto p(1,1);
CSegmento r(p,2,0);
CCirculo c(p,2);
// rellena la lista con obstáculos
lo.push_back(&r);
lo.push_back(&c);
Se introduce la dirección, ya que
// recorre la lista de obstáculos
la
lista es de punteros a obstáculos
ilo=lo.begin();
cout << "La lista es: " << endl;
for (int i = 0; i < lo.size() ; i++, ilo++)
(*ilo)->Identificacion (cout);
return 0;
}
Prof. Álvaro Sánchez Miralles
*ilo es el contenido del nodo de la lista;
es decir, es un puntero a obstáculo
UPCO ICAI Departamento de Electrónica y Automática 10
Programación en C++
Clases abstractas
•
Son clases que tienen al menos una función virtual sin
código
– Cada vez que se crea una clase derivada de esas clases
abstractas hay que codificar las funciones que faltan
– No se pueden declarar objetos de la clase base porque falta el
código de algunas funciones.
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 11
Programación en C++
Ejemplo herencia completo (I)
Objetivo: Sobrecargar el operador << para
class CObstaculo
admitir salida de datos de cualquier clase que
{
herede de obstáculos
private:
double m_opacidad;
public:
~CObstaculo(){};
// constructores
CObstaculo(){ m_opacidad = 0;}
CObstaculo(double opacidad)
{m_opacidad = opacidad;};
friend ostream& operator<<(ostream &o, CObstaculo* obs );
virtual void Imp(ostream& o)=0;
Imp permite hacer polimorfismo en <<,
};
ya que este operador es amigo
ostream& operator<<(ostream &o, CObstaculo* obs)
{
obs->Imp(o);
return o;
}
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 12
Programación en C++
Ejemplo herencia completo (II)
class CSegmento : public CObstaculo
{
...
public:
~CSegmento(){};
// constructores
... ver trasparencias anteriores
CSegmento& operator=(const CSegmento& r);
friend ostream& operator<<(ostream &o, CSegmento& r);
void Imp(ostream& o){o<<*this;}
Sobrecarga de Imp
};
CSegmento& CSegmento::operator=(const CSegmento& r){
m_p1 = r.m_p1; m_p2 = r.m_p2; m_longitud = r.m_longitud;
m_pendiente = r.m_pendiente; return(*this);
}
ostream& operator<<(ostream &o, CSegmento& r){
o << "Segmento: " << r.m_p1 << " " << r.m_p2 << endl;
return o;
}
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 13
Programación en C++
Ejemplo herencia completo (III)
class CCirculo: public CObstaculo
{
...
public:
~CCirculo(){};
// constructores
... ver trasparencias anteriores
CCirculo& operator=(const CCirculo& c);
friend ostream& operator<<(ostream &o, CCirculo& r);
void Imp(ostream& o){o<<*this;}
};
ostream& operator<<(ostream &o, CCirculo& r){
o << "Circulo: " << r.m_p1 << " " << r.m_diametro << endl;
return o;
}
CCirculo& CCirculo::operator=(const CCirculo& c){
m_diametro = c.m_diametro; m_p1 = c.m_p1;
return(*this);
}
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 14
Programación en C++
Ejemplo herencia completo (IV)
class CPunto
A continuación el resto de código
{
no relevante que falta
private:
double m_x;
double m_y;
public:
double x(){return m_x;}
double y(){return m_y;}
CPunto(){Punto(0,0);}
CPunto(double x, double y){Punto(x,y);}
CPunto(const CPunto& p){m_x = p.m_x; m_y = p.m_y;}
CPunto& operator=(const CPunto& p)
{m_x = p.m_x; m_y = p.m_y; return(*this);}
void Punto(double x, double y) {m_x = x; m_y=y;}
CPunto& operator+=(CPunto& p)
{m_x += p.m_x; m_y += p.m_y; return(*this);}
CPunto& operator*=(double p){m_x *= p; m_y *= p; return(*this);}
CPunto& operator/=(double p){m_x /= p; m_y /= p; return(*this);}
CPunto& operator-=(CPunto& p)
{m_x -= p.m_x; m_y -= p.m_y; return(*this);}
friend ostream& operator<<(ostream &o, CPunto& p);
};
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 15
Programación en C++
Ejemplo herencia completo (V)
ostream& operator<<(ostream &o, CPunto& p){
o << p.m_x << " " << p.m_y;
return o;
}
void CSegmento::Segmento(CPunto p1, double longitud, double pendiente){
double x,y;
m_longitud = longitud; m_pendiente = pendiente;
x = p1.x() + longitud*cos(pendiente*PI/180);
y = p1.y() + longitud*sin(-pendiente*PI/180);
m_p1.Punto(p1.x(),p1.y());
m_p2.Punto(x,y);
}
void CSegmento::Segmento(CPunto p1, CPunto p2){
m_p1 = p1; m_p2 = p2;
m_longitud = sqrt((p2.x()-p1.x())*(p2.x()-p1.x())+(p2.y()-p1.y())*(p2.y()p1.y()));
if (p2.x() == p1.x())
if (p2.y() > p1.y()) m_pendiente = -90;
else m_pendiente = 90;
else {
m_pendiente = atan((p1.y()-p2.y())/(p2.x()-p1.x()))*180/PI;
if ((p1.x() > p2.x()) && (p1.y() > p2.y())) m_pendiente += 180;
else if ((p1.x() > p2.x()) && (p1.y() < p2.y())) m_pendiente -= 180;
}
}
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 16
Programación en C++
Prueba herencia completo
#include <list>
using namespace std;
int main(int argc, char* argv[])
{
list<CObstaculo*> lo;
list<CObstaculo*>::iterator ilo;
CPunto p(1,1);
CSegmento r(p,2,0);
CCirculo c(p,2);
La lista es:
Segmento: 1 1 3 1
Circulo: 1 1 2
// rellena la lista con obstáculos
lo.push_back(&r);
lo.push_back(&c);
// recorre la lista con obstáculos
ilo=lo.begin();
cout << "La lista es: " << endl;
for (int i = 0; i < lo.size() ; i++, ilo++)
cout << *ilo;
cout << endl;
return 0;
}
Prof. Álvaro Sánchez Miralles
UPCO ICAI Departamento de Electrónica y Automática 17
Descargar