Está en la página 1de 52

Clases y objetos

lvaro Snchez Miralles Jos Porras (Fidel Fernndez)

ndice Conceptos iniciales Clases y objetos


Ejemplo para romper el hielo Definiciones Vida de un objeto

Funciones miembro
Constructor de un objeto Destructor de un objeto Sobrecarga de operadores Paso de parmetros por referencia Sobrecarga de constructor de copia Mejora del ejemplo

Diseo bsico en C++

Clases y objetos - 2

Conceptos iniciales

Modificador de tipo const Indica que un tipo permanece constante


Slo vale para evitar errores en tiempo de desarrollo const int LON=5; LON = 6; // ERROR int vi[LON]; const int *pi = vi; vi[0]=0; pi++; *pi=1; // ERROR int * const pii = vi; pii[0]=1; pii++; // ERROR const int * const piii = vi; piii++; // ERROR piii[1]=3; // ERROR
Clases y objetos - 4

Memoria dinmica I new


Reserva memoria

delete
Libera memoria main () { int *pi; pi = new int; double *pd=new double; delete pd; delete pi; int *pi=new int[10]; delete [] pi; }

Todo new tiene un delete asociado


Clases y objetos - 5

Memoria dinmica II Qu est mal?


main() { int *pi; pi = get_vector_discreto(1, 4); } /** funcin que devuelve un vector con los valores enteros * comprendidos entre min y max*/ int* get_vector_discreto(int min, int max){ int i, v[max-min]; for (i=0; i<max-min; i++) v[i] = i; return v; v es local !!!! }

Clases y objetos - 6

Memoria dinmica III Solucin con memoria dinmica


#define MAX 50 main() { int* pi; pi = get_vector_discreto(1, 4); } int* get_vector_discreto(int min, int max){ int i; int *pi = new int[max-min]; for (i=0; i<max-min; i++) pi[i] = i; return pi; }

Qu est mal?

Clases y objetos - 7

Memoria dinmica IV Solucin con memoria dinmica


main() { int* pi; pi = get_vector_discreto(1, 4); delete [] pi; } int* get_vector_discreto(int min, int max){ int i; int *pi = new int[max-min]; for (i=0; i<max-min; i++) pi[i] = i; return pi; }

Clases y objetos - 8

Clases y objetos

Ejemplo CComplejo I
#ifndef CCOMPLEJO_H #define CCOMPLEJO_H

CComplejo.h

/** * Descripcion: clase que representa a los nmeros complejos */

class CComplejo { private: double m_d_real; /** parte real*/ double m_d_imag; /** parte imaginaria*/ public: // constructores y destructor CComplejo(); CComplejo(double r, double i); ~CComplejo(); // funciones de acceso a miembros double getReal(); double getImag(); };
#endif
Clases y objetos - 10

Ejemplo CComplejo II
#include "CComplejo.h" #include <iostream> using namespace std; // ---------- constructores CComplejo::CComplejo(){ m_d_imag = 0; m_d_real = 0; cout << "Me han creado por defecto" << endl; } CComplejo::CComplejo(double r, double i){ m_d_imag = i; m_d_real = r; cout << "Me han creado con r = " << m_d_real << " e i = " << m_d_imag << endl; }
Clases y objetos - 11

CComplejo.cpp

Ejemplo CComplejo III

CComplejo::~CComplejo(){ cout << "Me han eliminado (" << m_d_real << "," << m_d_imag << ")" << endl; } // ---------- funciones de acceso a miembros double CComplejo::getReal(){ return m_d_real; } CComplejo.cpp double CComplejo::getImag(){ return m_d_imag; }

Clases y objetos - 12

Ejemplo CComplejo IV
#include "CComplejo.h" main.cpp

void pruComplejos(){ CComplejo C1,C2; cout << "Dentro de pruComplejos" << endl; Me han creado por defecto } Antes de llamar a pruComplejos Me han creado por defecto void main(void) Me han creado por defecto { Dentro de pruComplejos CComplejo C1; Me han eliminado cout << "Antes de llamar a pruComplejos" << (0,0) endl; Me han eliminado (0,0) pruComplejos(); Fuera pruComplejos cout << "Fuera de pruComplejos" << de endl; Me han creado con r = 0 e i = 3 CComplejo C2(0,3); Antes del final cout << "Antes del final" << endl; Me han eliminado (0,3) } Me han eliminado (0,0)
Clases y objetos - 13

Ejemplo CComplejo V Y el main con memoria dinmica?


void main(void) Qu est { mal? CComplejo *C1 = new CComplejo(); cout << "Antes de llamar a pruComplejos" << endl; pruComplejos(); cout << "Fuera de pruComplejos" << endl; CComplejo *C2 = new CComplejo(0,3); cout << "Antes del final" << endl; }

Clases y objetos - 14

Ejemplo CComplejo VI Y el main con memoria dinmica?


void main(void) { CComplejo *C1 = new CComplejo(); cout << "Antes de llamar a pruComplejos" << endl; pruComplejos(); cout << "Fuera de pruComplejos" << endl; CComplejo *C2 = new CComplejo(0,3); cout << "Antes del final" << endl; delete C1; delete C2; }

Clases y objetos - 15

Definicin de una clase I Una clase es un tipo de datos que tiene cuatro atributos asociados:
Variables miembro Funciones miembro Niveles de acceso tanto a las variables miembro como a las funciones miembro. private: no se puede acceder desde fuera de la clase. Oculta la informacin. public: se puede acceder desde fuera protected: slo las clases hijas de esta clase pueden acceder a la informacin (se ver ms adelante). Un nombre como etiqueta que sirve para identificar al nuevo tipo definido por la clase

Clases y objetos - 16

Definicin de una clase II


class CClase { // Privada por defecto public: // Accesible desde fuera protected: // Acceso restringido private: // Inaccesible desde fuera };
Clases y objetos - 17

Definicin de una clase III Elementos de una clase:


Variables miembro (Atributos). En el nombre se aade al principio m_, como por ejemplo double m_d_real. Funciones miembro (Mtodos).

Un objeto es un elemento de una determinada clase.


Clase nmero complejo CComplejo. C1, C2 son objetos de clase CComplejo.

Estado del objeto


Lo definen las variables miembro No se debe poder acceder desde fuera del objeto

Comportamiento del objeto


Lo definen las funciones miembro

Objeto es a clase como variable es a tipo.


Clases y objetos - 18

Vida de un objeto Igual que un tipo bsico Creacin de un objeto


Se reserva en memoria espacio para los datos internos del objeto. Se llama a una funcin para inicializar estos datos: constructor del objeto.

Acceso al objeto a travs de las funciones miembro visibles. Destruccin de un objeto


Al igual que despus de reservar espacio se llama al constructor del objeto, antes de destruirlo se llama al destructor del objeto.

Clases y objetos - 19

Funciones miembro de una clase

Constructores de un objeto Son funciones miembro cuyo nombre es el nombre de la clase.


No se puede llamar directamente

Cada vez que se crea un objeto de una clase, se crea espacio de forma automtica para las variables miembro y a continuacin se llama al constructor para que termine de inicializarlas Siempre hay dos constructores por defecto:
Sin parmetros: no hace nada. Desde otro objeto: inicializa las variables miembros con el valor que tienen en el otro objeto.

Se pueden definir constructores adicionales con parmetros, que a su vez tengan valores por defecto.
Clases y objetos - 21

Destructor de un objeto Es una funcin miembro de la clase cuyo nombre es el nombre de la clase acompaado ~.
No se puede llamar directamente

Cuando un objeto va a ser eliminado de un programa, antes de liberar la memoria asignada a sus variables miembro, se llama al destructor. Hay un destructor por defecto que no hace nada. El destructor se puede sobrecargar:
Esto es muy til en el caso de variables que utilicen memoria dinmica para poderla liberar.

El destructor no lleva parmetros. Slo puede haber un destructor

Clases y objetos - 22

El operador de asignacin = (I) Al igual que en los tipos bsicos (int, double, etc) las clases tienen automticamente asociadas un operador de asignacin (=) entre objetos de una misma clase. Por defecto, al asignar un objeto a otro de la misma clase hay una asignacin o copia miembro a miembro. Se puede redefinir esta asignacin (sobrecarga del operador =)

Clases y objetos - 23

El operador de asignacin = (II)


void main(void) OJO! Acceso a { miembro CComplejo C1(0,1), C2; C2 = C1; cout << "C2 = (" << C2.getReal() << "," << C2.getImag() << ")" << endl; }

Me Me C2 Me Me

han creado con r = 0 e i = 1 han creado por defecto = (0,1) han eliminado (0,1) han eliminado (0,1)

Clases y objetos - 24

El operador de asignacin = (III) Y el main con memoria dinmica?


void main(void) OJO! Acceso a { miembro CComplejo *C1, *C2; C1 = new CComplejo(0,1); *C2 = *C1; cout << "C2 = (" << C2->getReal() << "," << C2->getImag() << ")" << endl; delete C1; delete C2; }

Clases y objetos - 25

Sobrecarga de operador = (I)


class CComplejo { private: double m_d_real; /** parte real*/ double m_d_imag; /** parte imaginaria*/ public: // constructores y destructor CComplejo(); CComplejo(double r, double i); ~CComplejo(); // funciones de acceso a miembros double getReal(); double getImag(); void operator=(CComplejo c); };

Clases y objetos - 26

Sobrecarga de operador = (II) Es importante si la clase tiene miembros que son memoria dinmica
void CComplejo::operator=(CComplejo c){ m_d_real=c.m_d_real; m_d_imag=c.m_d_imag; cout << "Operador igualdad" << endl; }

OJO! Acceso a zona privada

Clases y objetos - 27

Sobrecarga de operador = (III)


void main(void) { CComplejo C1(0,1), C2; C2 = C1; cout << "C2 = (" << C2.getReal() << "," << C2.getImag() << ")" << endl; }
He creado dos objetos y se eliminan tres !!

Me han creado con r = 0 e i = 1 Me han creado por defecto Operador igualdad Me han eliminado (0,1) C2 = (0,1) Me han eliminado (0,1) Me han eliminado (0,1)
Clases y objetos - 28

Paso por referencia (I)


class CComplejo { private: double m_d_real; /** parte real*/ double m_d_imag; /** parte imaginaria*/ public: // constructores y destructor CComplejo(); CComplejo(double r, double i); ~CComplejo(); // funciones de acceso a miembros double getReal(); double getImag(); void operator=(const CComplejo& c); };

Clases y objetos - 29

Paso por referencia (II)


void main(void) { CComplejo C1(0,1), C2; Uhm, qu C2 = C1; raro!! cout << "C2 = (" << C2.getReal() << "," << C2.getImag() << ")" << endl; } void CComplejo::operator=(const CComplejo& c){ m_d_real=c.m_d_real; m_d_imag=c.m_d_imag; cout << "Operador igualdad" << endl; } Me han creado con r = 0 e i = 1 Me han creado por defecto Operador igualdad C2 = (0,1) Me han eliminado (0,1) Me han eliminado (0,1)
Clases y objetos - 30

Sobrecarga del constructor de copia (I)


class CComplejo { private: double m_d_real; /** parte real*/ double m_d_imag; /** parte imaginaria*/ public: // constructores y destructor CComplejo(); CComplejo(double r, double i); CComplejo(const CComplejo& c); ~CComplejo(); // funciones de acceso a miembros double getReal(); double getImag(); void operator=(const CComplejo& c); };

Clases y objetos - 31

Sobrecarga de constructor de copia (II)


void copia(CComplejo c){ cout << "Dentro de copia (" << c.getReal() << "," << c.getImag() << ")" << endl; } void main(void) { CComplejo C1(0,1); copia(C1); }

Se puede quitar la referencia?

CComplejo::CComplejo(const CComplejo& c){ m_d_real=c.m_d_real; m_d_imag=c.m_d_imag; cout << "Me han creado por copia de (" << c.m_d_real << "," << c.m_d_imag << ")" << endl; }
Clases y objetos - 32

Sobrecarga de constructor de copia (III)


void copia(CComplejo c){ cout << "Dentro de copia (" << c.getReal() << "," << c.getImag() << ")" << endl; } void main(void) { CComplejo C1(0,1); copia(C1); }

Cmo se evita la copia?

Me han Me han Dentro Me han Me han

creado con r = 0 e i = 1 creado por copia de (0,1) de copia (0,1) eliminado (0,1) eliminado (0,1)
Clases y objetos - 33

Definicin del operador << (I)


#include <iostream> class CComplejo { private: double m_d_real; /** parte real*/ double m_d_imag; /** parte imaginaria*/ public: // constructores y destructor ... void operator=(const CComplejo& c); friend std::ostream& operator<<(std::ostream &o, const CComplejo& c); }; Es una funcin que no es de la clase, pero que puede acceder a la parte privada de la misma
Clases y objetos - 34

Definicin del operador << (II)


ostream& operator<<(ostream &o, const CComplejo& c){ o << "(" << c.m_d_real << "," << c.m_d_imag << ")"; return o; } OJO! Acceso a zona privada

void main(void) { CComplejo C1(0,1); cout << "C1: " << C1 << endl; } Me han creado con r = 0 e i = 1 C1: (0,1) Me han eliminado (0,1)
Clases y objetos - 35

Mejora de la clase CComplejo (I) Que pasa si en vez de querer sacar por pantalla el complejo en formato (r,i) se quiere en [r,i]?
CComplejo::CComplejo(const CComplejo& c){ m_d_real=c.m_d_real; m_d_imag=c.m_d_imag; cout << "Me han creado por copia de " << c << endl; } CComplejo::CComplejo(double r, double i){ m_d_imag = i; m_d_real = r; cout << "Me han creado con " << *this << endl; } CComplejo::~CComplejo(){ cout << "Me han eliminado " << *this << endl; } this es un puntero al objeto en ejecucin
Clases y objetos - 36

Mejora de la clase CComplejo (II) Quitar ms cdigo duplicado


CComplejo::CComplejo(const CComplejo& c){ *this = c; cout << "Me han creado por copia de " << c << endl; }

Clases y objetos - 37

Funciones miembro de una clase Representan los mtodos a travs de los cuales se establece relacin con el objeto. El nombre de la funcin representa la accin a realizar por el objeto. Para mantener la integridad del objeto, toda comunicacin con el objeto debera ser a travs de la funciones miembro: Si una funcin externa a la clase quiere acceder a informacin interna como es el caso de >> o << de iostream debe ser declarada como amiga en la zona pblica (friend). Se pueden sobrecargar los nombres de las funciones.

Clases y objetos - 38

Resumen hasta ahora Toda clase debe tener


Destructor Constructor de copia que llama al operador = Operador = sobrecargado Constructor por defecto Funciones de acceso a miembros

Siempre que se pueda se pasan los objetos por referencia No olvidarse del uso de const

Clases y objetos - 39

Definicin del operador + (I)


CComplejo CComplejo::operator+(const CComplejo c){ CComplejo t; t.m_d_real=m_d_real+c.m_d_real; t.m_d_imag=m_d_imag+c.m_d_imag; cout << "Suma de complejos" << endl; return t; }

Clases y objetos - 40

Definicin del operador + (II)


void main(void) { CComplejo C1(0,1), C2(2,3), C3; C3 = C1 + C2; cout << "C3: " << C3 << endl; Me han creado con (0,1) }
Inicialmente eran 3 objetos y he necesitado 6

Me han creado con (2,3) Me han creado por defecto Operador igualdad Me han creado por copia de (2,3) Me han creado por defecto Suma de complejos Operador igualdad Me han creado por copia de (2,4) Me han eliminado (2,4) Me han eliminado (2,3) Operador igualdad Me han eliminado (2,4) C3: (2,4) Me han eliminado (2,4) Me han eliminado (2,3) Me han eliminado (0,1) Clases y objetos - 41

Definicin del operador + (III)


CComplejo CComplejo::operator+(const CComplejo& c){ CComplejo t; t.m_d_real=m_d_real+c.m_d_real; t.m_d_imag=m_d_imag+c.m_d_imag; cout << "Suma de complejos" << endl; return t; }

Clases y objetos - 42

Definicin del operador + (IV)


void main(void) { CComplejo C1(0,1), C2(2,3), C3; C3 = C1 + C2; cout << "C3: " << C3 << endl; } Me han creado con (0,1) Me han creado con (2,3) Sigue Me han creado por defecto habiendo Me han creado por defecto muchos Suma de complejos objetos Operador igualdad Me han creado por copia de (2,4) Me han eliminado (2,4) Operador igualdad Me han eliminado (2,4) C3: (2,4) Me han eliminado (2,4) Me han eliminado (2,3) Me han eliminado (0,1) Clases y objetos - 43

Definicin del operador + (V)


CComplejo& CComplejo::operator+(const CComplejo& c){ CComplejo t; t.m_d_real = m_d_real+c.m_d_real; t.m_d_imag = m_d_imag+c.m_d_imag; cout << "Suma de complejos" << endl; return t; }

CComplejo& CComplejo::operator+(const CComplejo& c){ m_d_real+=c.m_d_real; m_d_imag+=c.m_d_imag; cout << "Suma de complejos" << endl; return *this; }

Clases y objetos - 44

Definicin del operador + (VI)


void main(void) { CComplejo C1(0,1), C2(2,3), C3; C3 = C1 + C2; cout << "C3: " << C3 << endl; } Aqu hay algo raro! Me han creado con (0,1) Me han creado con (2,3) Me han creado por defecto Suma de complejos Operador igualdad C3: (2,4) Me han eliminado (2,4) Me han eliminado (2,3) Me han eliminado (2,4)

Clases y objetos - 45

Definicin del operador + (VII)


void CComplejo::operator+=(const CComplejo& c){ m_d_real+=c.m_d_real; m_d_imag+=c.m_d_imag; cout << "Suma monaria de complejos" << endl; }

Clases y objetos - 46

Definicin del operador + (VIII)


void main(void) { CComplejo C1(0,1), C2(2,3); C1 += C2; cout << "C1: " << C1 << endl; }

Me han creado con (0,1) Me han creado con (2,3) Suma monaria de complejos C1: (2,4) Me han eliminado (2,3) Me han eliminado (2,4)

Clases y objetos - 47

Definicin del operador + (IX) Mejora del operador +


CComplejo CComplejo::operator+(const CComplejo& c){ CComplejo t = *this; t += c; return t; }

Clases y objetos - 48

Sobrecarga de operadores Los operadores de C++ funcionan exactamente igual que una funcin:
CComplejo C1,C2,C3; C1=C2+C3; C1.operator=(C2.operator+(C3));

Siempre hay definido por defecto: = y & para cualquier clase (por supuesto, se pueden sobrecargar). Permiten definir un lgebra de los objetos de una clase. No se debe abusar. Si a partir del operador no se sabe claramente la accin a realizar es mejor utilizar funciones.
Clases y objetos - 49

Ejercicios con operadores Definir el operador > de CComplejo Definir el operador+ pero que sea friend de CComplejo Definir el operador + para trabajar con punteros de CComplejo

En C++ las funciones pueden tener el mismo nombre, si los parmetros son distintos

Clases y objetos - 50

Diseo bsico en C++

C++. Un nuevo estilo de programacin Programacin estructurada


La solucin del problema se consigue construyendo un programa formado por funciones, cada una especializada en resolver una parte del problema. Los datos son intercambiados entre funciones bajo control del programa principal.

Programacin orientada a objetos


La solucin del problema es un conjunto de objetos que interactan entre s, a travs de sus interfaces. Ninguno sabe como funciona el otro por dentro.
Programa principal Datos Objeto1 Objeto3 Funcin1 Funcin2 Funcin3 Objeto4 Objeto2

Clases y objetos - 52