Vous êtes sur la page 1sur 9

Clases en C

Creacin de clases en C++ (I)


Programacin Orientada a Objeto Ing. Civil en Telecomunicaciones

Convertir estructura InfoAlumno en una clase Escribir una clase simple en C++, con
Constructores Sobrecarga de operadores

Estructura de datos por alumno


Estructura de datos que almacena informacin de cada alumno
struct InfoAlumno { std::string nombre; double examen1, examen2; std::vector<double> notas; };

Principio de ocultamiento de informacin (Information hiding)


Al programador se le debe
Esconder los detalles de la implementacin

Podra ser cambiada o mejorada en el tiempo


Esconder los datos

Limitar fuentes de errores

Problema: programadores acceden directamente a los elementos de los datos del tipo InfoAlumno

Exponer slo lo necesario para poder manipular la informacin (interfaz)


Exponer los mtodos mediante los cuales

acceder a los datos

La interfaz debe ser inmutable

Interfaz para InfoAlumno


Agregar dos funciones miembros a estructura InfoAlumno
struct InfoAlumno { std::string nombre; double examen1, examen2; std::vector<double> notas; std::istream& leeAlumnos(std::istream&); double nota() const; };

Funcin miembro de lectura de datos


Funcin es parte de una estructura InfoAlumno
Nombre debe ser InfoAlumno::leeAlumnos No necesita recibir la estructura

como argumento

Tiene acceso directo a datos de estructura


istream& InfoAlumno::leeAlumnos(istream& in) { in >> nombre >> examen1 >> examen2; // Llama a funcion leeNotas() anterior leeNotas(in, notas); return in; }

2013 Mario Medina C.

Funcin miembro nota()


Invoca a funcin notas() que no es miembro de InfoAlumno
Versin que recibe dos doubles y un

Proteccin de datos
Programadores pueden acceder a estructura a travs de funciones miembros
Pero tambin pueden acceder directamente

vector<double>

Funcin miembro const


No puede modificar datos de la estructura
double InfoAlumno::nota() const { return ::nota(examen1, examen2, notas); }

a los datos

Solucin: proteger los datos


public: accesible a todo el cdigo private: accesible slo a funciones

miembros de InfoAlumno

Clase InfoAlumno
class InfoAlumno { public: // Define la interfaz std::istream& leeAlumnos(std::istream&); double nota() const; private: // Define la implementacin std::string nombre; double examen1, examen2; std::vector<double> notas; };

class y struct
La nica diferencia entre class y struct es la proteccin por omisin
Proteccin por omisin en una clase es

private
En una estructura, la proteccin por omisin

es public

En general, se prefiere usar class para clases de C++ y struct para estructuras de C

Funciones de acceso
Ejemplo anterior tiene los datos privados
Cmo se puede conocer sus valores?

Clase InfoAlumno
class InfoAlumno { public: // Define la interfaz std::istream& leeAlumnos(std::istream&); double nota() const; std::string nombre() const { return n; } private: // Define la implementacin std::string n; double examen1, examen2; std::vector<double> notas; };

Mediante funciones de acceso (accessor functions) Ejemplo: se necesita acceso al nombre del alumno para imprimir el informe
std::string nombre() const { return n; }

2013 Mario Medina C.

Funcin nombre()
Nombre de variable cambiada para evitar conflictos entre el dato n y la funcin Funcin miembro const
No puede modificar variable n Por eso, retorna copia de string en vez de

Funciones en lnea (inline functions)


En C, comando inline declara una funcin en lnea
Sugerencias al compilador

Compilador expande funciones in situ


Mltiples copias del cdigo Evita costo de llamada a funcin

referencia a string

Funcin est definida dentro de la clase


Funcin en lnea (inline

function)

Funciones miembro definidas dentro de la definicin de la clase son funciones en lnea

Funcin compara()
Funcin no-miembro utilizada para ordenar los registros InfoAlumno en forma alfabtica Acceso a nombre de alumno via funcin de acceso nombre()
bool compara(const InfoAlumno& x, const InfoAlumno& y) { return x.nombre() < y.nombre(); }

Funcin valido()
Funcin en lnea que verifica que exista al menos una nota de tarea
Usa funcin miembro de vector .empty()
class InfoAlumno { public: bool valido() const { return !notas.empty(); } }

Clase InfoAlumno
class InfoAlumno { public: // Define la interfaz std::istream& leeAlumnos(std::istream&); double nota() const; std::string nombre() const { return n; } bool valido() const { return !notas.empty(); } private: // Define la implementacin std::string n; double examen1, examen2; std::vector<double> notas; }; bool compara(const InfoAlumno&, const InfoAlumno&);

Constructores
Cmo crear un nuevo objeto InfoAlumno?
Mediante una funcin constructor Funciones miembro especiales que crean un

objeto y (quizs) lo inicializan

No son invocadas directamente


Se invocan al crear un nuevo objeto

2013 Mario Medina C.

Constructores
Objetos de bibliotecas estndar incluyen constructores para objetos vacos e inicializaciones Compilador genera constructor vaco por omisin
Inicializa variables miembros a un valor que

Inicializacin de objetos
Inicializacin por omisin
Para objetos de una clase dada

depende del tipo de objeto creado

Clase debe incluir una funcin de inicializacin por omisin Creacin de objetos string invoca constructor por omisin de objetos string Crea un objeto string vaco
Para primitivas bsicas

Variables son indefinidas

Inicializacin de objetos
Inicializacin por valor Algunos contenedores como map inicializan primitivas bsicas por valor
Al crear un nuevo elemento pair de map, se

Constructor de InfoAlumno
Objeto InfoAlumno contiene 4 elementos:
std::string (inicializado a string vaco) std::vector (inicializado a vector vaco) Dos variables double

crea un entero de tipo int inicializado a cero

Es necesario inicializarlas explcitamente

Constructor de InfoAlumno
Constructor vaco
InfoAlumno::InfoAlumno(): examen1(0), examen2(0) { } Compilador convierte int a double

Clase InfoAlumno (I)


// Clase que almacena la informacion de un alumno class InfoAlumno { public: // Define la interfaz InfoAlumno() : examen1(0), examen2(0) {} InfoAlumno(std::istream& in) { leeAlumnos(in); } std::istream& leeAlumnos(std::istream& in) { in >> n >> examen1 >> examen2; leeNotas(in, notas); return in; }

Constructor a partir de flujo de entrada


InfoAlumno::InfoAlumno(istream& in) { leeNotas(in); }

2013 Mario Medina C.

Clase InfoAlumno (II)


double nota() const { return ::nota(examen1, examen2, notas); } std::string nombre() const { return n; } bool valido() const { return !notas.empty(); }

Clase InfoAlumno (III)


private: // Define la implementacin std::string n; double examen1, examen2; std::vector<double> notas; istream& leeNotas(istream& in, vector<double>& notas) { if (in) { notas.clear(); double temp; while (in >> temp) { notas.push_back(temp); } in.clear(); } return in; } };

Usando la clase InfoAlumno (I)


int main() { vector<InfoAlumno> alumnos; InfoAlumno alumno; string::size_type maxlen = 0; // Lee los datos desde entrada estandar while(alumno.leeAlumnos(cin)) { maxlen = max(maxlen, alumno.nombre().size()); alumnos.push_back(alumno); }

Usando la clase InfoAlumno (II)


// Ordena los registros de alumnos sort(alumnos.begin(), alumnos.end(), compara); // Escribe los nombres y las notas for (vector<InfoAlumno>::size_type i = 0; i != alumnos.size(); ++i) { cout << alumnos[i].nombre() << string(maxlen + 1 alumnos[i].nombre().size(), ' ');

Usando la clase InfoAlumno (III)


try { double nota_final = alumnos[i].nota(); streamsize prec = cout.precision(); cout << setprecision(3) << nota_final << setprecision(prec) << endl; } catch(domain_error e) { cout << e.what() << endl; } } return 0; }

Ejemplo: la clase punto


La clase punto representa un punto en el espacio cartesiano
Tiene dos variables miembro:

x_coord y_coord

// coordenada x // coordenada y

Como primera idea, construir una estructura

punto de lenguaje C, y convertirla en una clase de C++

2013 Mario Medina C.

struct versus class


// Estructura de C struct punto { double x_coord; double y_coord; }; // Clase de C++ class punto { double x_coord; double y_coord; };

Agregar funciones de acceso


class punto { // Interface public: double x() const { return x_coord; } double y() const { return y_coord; } void setX(double x) { x_coord = x; } void setY(double y) { y_coord = y; } // Implementacion private: double x_coord; double y_coord; };

Ahora, agregaremos funciones miembro a la clase

Definir constructor vaco


Constructor vaco inicializa variables miembro a 0.0
punto():x_coord(0), y_coord(0) { }

Definir constructor con argumentos


Constructor inicializa variables miembro a partir de los argumentos
punto(double x, double y) { x_coord = x; y_coord = x; }

Otra forma de escribir el constructor vaco


punto() { x_coord = 0.0; y_coord = 0.0; }

Forma de uso
punto p1, p2(1.0, 2.0);

Operaciones con objetos punto


Nos gustara poder usar las operaciones aritmticas comunes con objetos puntos
Suma, resta, multiplicacin, divisin por una

Comparando puntos
Dos puntos son iguales si sus componentes son iguales y diferentes si sus componentes son diferentes
bool operator==(punto& p) { return(x_coord == p.x() && y_coord == p.y()); } bool operator!=(punto& p) { return !(x_coord == p.x() && y_coord == p.y()); }

constante Suma y resta de dos objetos punto Comparacin de objetos punto

Cmo? Sobrecargando los operadores estndar

Uso: cout << (p1 == p2) << endl;

2013 Mario Medina C.

Comparando puntos
Ambas funciones anteriores son funciones miembro de la clase punto Comparacin de objetos punto p1 == p2 es interpretada por el compilador como p1.==(p2)
Se llama a la funcin miembro

Multiplicando punto por constante


Multiplicar un punto por una constante k multiplica sus componentes por la constante
Operacin debera retornar un nuevo objeto

punto

No modifica el objeto actual

correspondiente

Cmo crear un nuevo objeto punto?


Solicitar creacin de objeto al sistema via

comando new

Multiplicando punto por constante


punto operator*(double k) const { punto *temp = new punto; temp->setX(x_coord*k); temp->setY(y_coord*k); return *temp; }

Creacin dinmica de objetos


La expresin new T crea un nuevo objeto del tipo clase T
Expresin retorna un puntero al nuevo objeto Objeto inicializado por omisin

Lo mismo puede hacerse para la divisin


Uso:

Tambin puede ser inicializado con argumentos InfoAlumno *ia = new InfoAlumno(); punto *p = new punto();
Objeto se elimina con delete

p2 = (p1/5.0)*9.0;

delete ia;

Creacin dinmica de vectores


La expresin new T[n] crea un vector de n objetos del tipo clase T
Expresin retorna un puntero de tipo T* al

Suma punto con constante


punto operator+(double k) { punto *temp = new punto; temp->setX(x_coord + k); temp->setY(y_coord + k); return *temp; }
Pero, qu pasa al sumar un punto con

primer elemento del vector Todos los objetos inicializados por omisin
Inicializados a travs del constructor por omisin
Vector se elimina con delete[]

Elementos son destruidos en orden inverso de creacin

otro punto?

2013 Mario Medina C.

Suma punto con otro punto


punto operator+(const punto& p) { punto *temp = new punto; temp->setX(x_coord + p.x()); temp->setY(y_coord + p.y()); return *temp; }

Sobrecarga de operaciones += y -=
Operacin A += B sobreescribe A con la suma de A + B Sobrecarga de operador debe modificar objeto y retornar objeto modificado Cmo puede un objeto retornarse a s mismo?
Comando this hace referencia al objeto

Cmo sabe el sistema cul funcin usar?


Por los argumentos:

p1 = p2 + 3; p3 = p1 + p2;

Sobrecarga de operador +=
punto& operator+=(double k) { x_coord = x_coord + k; y_coord = y_coord + k; return *this; } punto& operator+=(const punto& p) { x_coord = x_coord + p.x(); y_coord = y_coord + p.y(); return *this; }

Sobrecarga de operador *=
punto& operator*=(double k) { x_coord = x_coord*k; y_coord = y_coord*k; return *this; } punto& operator*=(const punto& p) { }

Funcin debe retornar referencia al objeto actual, no una copia!

Pero, qu debera hacer esto?

Sobrecarga de operador *=
Qu debera hacer la multiplicacin de dos objetos punto p1*p2?
Producto punto interno Producto cruz externo Multiplicacin elemento-a-elemento

Reglas bsicas de sobrecarga de operadores


1. No sobrecargar un operador si la operacin no es obvia 2. Siempre atenerse a la semntica obvia de la operacin

A B resta el valor de B de A

Slo sobrecargar operadores si la operacin a realizar sobre los objetos est claramente definida

3. Siempre proveer las operaciones relacionadas


Si se sobrecarga +, tambin sobrecargar +=

2013 Mario Medina C.

Operadores que pueden sobrecargarse


Aritmticos: + - * / += -= *= /= ++ -+(unario) -(unario) Manipulacin de bits: & | ^ << >> &= |= ^= <<= >>= ~ Comparacin: == != < > <= >= || && ! (unario) Manejo de memoria: new new[] delete delete[] Otros: () , [] -> * &(prefijos)

Sobrecarga mediante funciones nomiembro


Operadores pueden ser sobrecargados en funciones miembro no-miembro
Funciones no-miembro reciben dos

operandos
Declaradas fuera de la clase
Funciones miembro tienen un operando

implcito: el objeto al cual pertenecen


Declaradas dentro de la clase

Sobrecarga de == usando funcin no-miembro


La siguiente funcin no-miembro compara dos objetos punto
bool operator==(const punto& p1, const punto p2) { return(p1.x() == p2.x() && p2.x() == p2.y()); }

Funciones miembro vs. no-miembro


Operadores =, ->, [], (), slo pueden sobrecargarse como funciones miembro Operadores =<<, >> slo pueden sobrecargarse en funciones no-miembro Operadores unarios: recomendable sobrecargar en funciones miembro Operadores binarios que tratan ambos argumentos de igual forma: recomendble sobrecargar en funciones no-miembro Operadores binarios que modifican argumento: recomendable sobrecargar en funciones miembro

Cmo debera sobrecargarse el operador ==?

2013 Mario Medina C.

Vous aimerez peut-être aussi