Upload
duongdien
View
221
Download
0
Embed Size (px)
Citation preview
Constructor no-argConstructor no-argclass Point3D {int x;//campos private por defectoint y;int z;public://uso lista de inicializadores Point3D (int x1, int y1, int z1): x(x1), y(y1), z(z1) {}Point3D (): x(0), y(0), z(0) {}//no arg, inicializa al origenPoint3D (int low, int high);//....};//en Point3D.cppPoint3D::Point3D (int low, int high) {x = low + int((rand() / RAND_MAX)) * (high - low);y = low + int((rand() / RAND_MAX)) * (high - low);z = low + int((rand() / RAND_MAX)) * (high - low);}//en main(), Point3D pt1;para el no-arg
Métodos get y setMétodos get y setclass Atleta{
char* nombre;//por defecto son private estos campos
int numero;
char* nacionalidad;
double tiempo;
public:
Atleta(char* n=NULL, int nro=0, char* p=NULL, double t=0.0);
char* getNombre(void) const;//tiene 2 cadenas con NULL, por defecto
int getNumero(void) const;
char* getNacionalidad(void) const;
double getTiempo(void) const;
void setNombre(char* n);
void setNumero(int n);
void setNacionalidad(char* n);
void setTiempo(double t);
void mostrarDatos(void) const;
~Atleta(void);};
Métodos get y setMétodos get y setAtleta::Atleta(char* n, int nro, char* p, double t){
nombre=new char[strlen(n) + 1];//reserva memoria dinámica
strcpy(nombre, n);
numero=nro;
nacionalidad=new char[strlen(p)+1];
strcpy(nacionalidad, p);
tiempo=t;}
char* Atleta::getNombre(void) const{
return nombre;}
void Atleta::setNombre(char *n) {
if(nombre==NULL){//si usé valores por defecto en el constructor
nombre=new char[strlen(n) + 1];//idem constructor para nombre
strcpy(nombre, n);}}
Métodos constMétodos const
//en Point3D.h
//no puedo escribir un campo en el lado izquierdo de
//asignación dentro de la definición de la función
//declarada const
//una función const no puede invocar un método de
//la clase Point3D que no haya sido declarado const
bool equals(Point3D q) const;//const al final header
bool equals(int x1, int y1, int z1) const;
Puntero thisPuntero thisbool Point3D::equals(Point3D q) const {//no hace falta el this
return (this->x == q.x && this->y == q.y && this->z == q.z);}
//función sobrecargada, distintos argumentos
bool Point3D::equals(int x1, int y1, int z1) const {//sin puntero this
return (x == x1 && y == y1 && z == z1);}
//en main(), compara punto pt4 con punto pt2 (2º versión)
cout << "Es este nuevo punto transladado pt4 igual a pt2? --> " << pt4.equals(pt2.getX(), pt2.getY(), pt2.getZ()) << endl;//simétrico
//primera versión de equals
cout << "Punto 1 ahora es: ( "<< pt1.getX() << ", " << pt1.getY() << ", " << pt1.getZ() << ")" << endl;
cout << "Es pt1 igual a pt2? --> "<< pt1.equals(pt2) << endl;
Argumentos por defectoArgumentos por defecto#pragma once
class Punto{double x;//privados por defectodouble y;
public:
Punto(double cx=0.0, double cy=0.0);
~Punto(void);//los args.por defecto
double getX(void);
double getY(void);
void setX(double cx);
void setY(double cy);
void mover(double dx, double dy);
void mostrarPunto(void);};
Argumentos por defectoArgumentos por defectoPunto::Punto(double cx, double cy){
x=cx;y=cy;}
//Tengo clases contenedorasclass Circulo{public:
Circulo(double r=1.0, double x=0.0, double y=0.0);double getRadio(void);void setRadio(double r);double area(void);void mostrarCirculo(void);void mover (double dx, double dy);~Circulo(void);
private:double radio;Punto centro;//contiene un objeto Punto como centro
};
Argumentos por defectoArgumentos por defecto//Forma correcta de inicializar en Circulo.cppCirculo::Circulo(double r, double x, double y):centro(x,y){
radio=r;}//Tengo otra clase contenedoraclass Anillo{public:
Anillo(double x=0.0, double y=0.0, double radio=1.0, double a=1.0);double getAncho(void);void setAncho(double a);double area(void);void mover(double dx, double dy);void mostrarAnillo(void);~Anillo(void);
private:Circulo interior;//contiene dos circulosCirculo exterior;double ancho;
};
Argumentos por defectoArgumentos por defecto
//Anillo.cpp
#include "Anillo.h"
//forma correcta de inicializar los dos circulos contenidos
Anillo::Anillo(double x=0.0, double y=0.0, double radio=1.0, double a=1.0):interior(x,y,radio), exterior(x,y,radio+ancho)
{
ancho=a;
}
Argumentos por defectoArgumentos por defecto#include <iostream>
using std::cout;
using std::endl;
class CStack{
public:
CStack(int n = 10);//pila con 10 elementos por defecto
~CStack();
void push(int i);
int pop();
void print();
private:
int* pList;//reserva dinámica de memoria
int size;
int next;};
Argumentos por defectoArgumentos por defecto
CStack::CStack(int n) : next(0), size(n){//siguiente es 0 al inicio
pList = new int[size];//luego next++;por cada inserción
}
Arrays de objetos de una Arrays de objetos de una claseclase
class Carriage {bool asientos [40]; bool primera;
public:Carriage() {};//no argCarriage(bool prim);bool getAsiento(int ind) { return asientos[ind]; }bool getPrimera() { return primera; }void setPrimera(bool p) { primera = p; }void ocupar();
};
Arrays de objetos de una Arrays de objetos de una claseclase
class Train {
Carriage * carriages;//reservo memoria dinámica para el array
int numPri;
int numSeg;
char * salida;
char * destino;
int precioPrimera;
int precioSegunda;
public: Train(int nP, int nS, char * sal, char * dest, int pP, int pS):
numPri(nP), numSeg(nS), salida(sal), destino(dest), precioPrimera(pP), precioSegunda(pS) {carriages = new Carriage[nP + nS];//crea array
for(int i = 0; i < nP + nS; i++) carriages[i].setPrimera(i < nP);}
~Train() { delete [] carriages; }
Carriage getCarriage(int i) { return carriages[i]; }
void llenar();
int totalVentas();};
Arrays de objetos de una Arrays de objetos de una claseclase
//pruebaSala.cpp
//…faltan include y using
int main(void){
Sala s1("Sala 1", 8,12,true);
Sala s2("Sala 2", 18,20,false);
Sala s3("Sala 3", 12,15,true);
Sala s[]={s1,s2,s3};
s1.mostrarDatos();
int eventos[4]={200,50,100,150};
for(int i=0;i<4;i++)
for(int j=0;j<3;j++)
if(s[j].calculaCapacidad()>=eventos[i])
cout<<"La sala "<<s[j].getNombre()<<" tiene capacidad para "<<eventos[i]<<" personas\n\n";
return 0;}
Miembros static de una Miembros static de una claseclase
class Camion {//clase de la práctica modificadaint nroruedas;static int nrocamiones;
public:
Camion(int nror);
//…
static int nroCamiones(void);
~Camion(void);};
Camion::Camion(int nror){
nroruedas=nror;
nrocamiones++;}//cuento camiones creados
int Camion::nrocamiones=0;//inicializo fuera de la //declaración!!
Miembros static de una Miembros static de una claseclase
//en Camion.cpp
int Camion::nroCamiones(void){
return nrocamiones;}
//archivo de prueba.cpp
int main(void)
{
Camion c(6);
Camion d(8);
cout<<"El nro. de camiones creados es: "<<Camion::nroCamiones()<<"\n";//2 camiones creados
return 0;
}
Punteros a objetos de una Punteros a objetos de una claseclase
class Carrera2{
int distancia;
Atleta** competidores;//array de Atletas manejados por *
int cantAtletas;
int indice;
public:
Carrera2(int d, int cantidad);
int getDistancia(void) const;
Atleta *getGanador(void) const;
int getCantAtletas(void) const;
void agregarAtleta(Atleta* p);
~Carrera2(void);};
Punteros a objetos de una Punteros a objetos de una claseclase
Carrera2::Carrera2(int d, int cantidad){
distancia=d;
cantAtletas=cantidad;
competidores=new Atleta* [cantidad];
indice=0;}
Atleta* Carrera2::getGanador(void) const{
double t=competidores[0]->getTiempo();//Uso de ->
double taux;
int iaux;
for(int i=1;i<cantAtletas;i++){
taux=competidores[i]->getTiempo();
if(taux<t){
t=taux;
iaux=i; }}
return competidores[iaux];}
Punteros a objetos de una Punteros a objetos de una claseclase
void Carrera2::agregarAtleta(Atleta* p){
if(indice<cantAtletas){
competidores[indice]=p;
indice++;
}}
Carrera2::~Carrera2(void)
{
delete[] competidores;
}
Punteros a objetos de una Punteros a objetos de una claseclase
int main(void){
Atleta a1("Juan Perez",1, "Argentina", 10.1);
Atleta a2("John Ford",2,"USA", 9.1);
Atleta *p=new Atleta("Juan Castro", 3, "Mexico", 7.3);
Carrera2 c3(300,3);
c3.agregarAtleta(&a1);
c3.agregarAtleta(&a2);
c3.agregarAtleta(p);
Atleta *r=c3.getGanador();
r->mostrarDatos();//acceso indirecto a través de *
delete p;//muestradatos del atleta ganador
return 0;}
Uso de referencias en C++Uso de referencias en C++• Una referencia en principio parece muy
similar a un puntero• Su importancia real se vuelve aparente
con su uso en argumentos de funciones, en especial en el contexto de la programación orientada a objetos
• A pesar de su simplicidad es un elemento muy potente y en algunos contextos alcanzaría resultados que serían imposibles de obtenerlos sin ellas
Uso de referencias en C++Uso de referencias en C++• Una referencia es un alias de otra variable
del mismo tipo, un equivalente completo de ella
• Es un nombre que puede usarse en lugar del nombre de la variable original. Debido a que es un alias y no un puntero, la variable de la cual es un alias tiene que especificarse cuando se declara dicha referencia y, a diferencia de un puntero, una referencia no puede alterarse para representar a otra variable (tampoco puede valer NULL)
Declaración e inicialización Declaración e inicialización de referenciasde referencias
• long number=0;• long& rnumber = number; // Declara una
//referencia a la variable number,• long &rnumber;//error• rnumber += 10;//number=10;• long* pnumber = &number; // Inicializa • //el puntero con la dirección de number• *pnumber += 10; // Incrementa number • //a través de un puntero• Al puntero necesito desreferenciarlo para usarlo,
a la referencia no
Declaración e inicialización Declaración e inicialización de referenciasde referencias
#include <iostream>
using std::cout;using std::endl;int main(){int a=10;int&b=a;cout<<&a<<"\t"<<&b<<endl;return 0;}Salida por pantalla:Parece puntero a dirección fija de memoria0012FF60 0012FF60 Presione una tecla para continuar . . .
Declaración e inicialización Declaración e inicialización de referenciasde referencias
• Pueden inicializarse a referencias del mismo tipo, en cuyo caso señalan al objeto inicial:
int& max (int& a, int& b) {
return (a >= b)? a : b;
}...
int x = 10, y = 30;
int& r1 = x; // Ok. r1 referencia a x
int& r2 = r1; // Ok. r2 referencia a x
int& r3 = max(x, y); // Ok. r3 referencia a y
Declaración e inicialización Declaración e inicialización de referenciasde referencias
• Después de la asignación inicial, las sucesivas asignaciones a las referencias deben ser con objetos del mismo tipo. Por ejemplo, a una referencia a int solo se le pueden asignar tipos int. Pero estas asignaciones son en realidad al objeto inicialmente referenciado.
int x = 10, y = 20;
int& refi = x; // definición inicial
cout << "X = " << refi; // -> X = 10 (valor de x)
refi = y; // Ojo!! Equivale a: x = y
cout << "X = " << refi; // -> X = 20 (x es ahora 20)
cout << "X = " << x; // -> X = 20 (comprobación)
Referencias como Referencias como argumentos de funcionesargumentos de funciones
// Funcion que incrementa una variable en 10int incr10(int& num) {//la ref.se crea e inicializa c/vez que //la función es invocada, o sea c/vez se crea
//una nueva referenciacout << endl<< “Valor recibido = “ << num;num += 10; // Incrementa el argumentoreturn num; // retorna el valor incrementado}//verdadero paso por referencia, en caso de
//punteros se pasa una copia del mismo, en C//se emula el paso por referencia con punteros//sino se quiere modificar el arg.se agrega const
Referencias como Referencias como argumentos de funcionesargumentos de funciones
int main(void){
int num = 3;
int value = 6;
int result = incr10(num);//error: incr10(20);una cte.no puede //modificarse!
cout << endl<< “incr10(num) = “ << result;
cout << endl<< “num = “ << num;
result = incr10(value);
cout << endl<< “incr10(value) = “ << result;
cout << endl<< “value = “ << value;
cout << endl;
return 0;}
Referencias como Referencias como argumentos de funcionesargumentos de funciones
Valor recibido = 3
incr10(num) = 13
num = 13
Valor recibido = 6
incr10(value) = 16
value = 16
RecomendacionesRecomendaciones• Cuando la función llamada no altera sus
argumentos, se debe pasar una copia de la variable.
• Cuando una función cambia el valor de sus argumentos, se debe pasar la dirección, a través de punteros.
• Las referencias se reservan para aquellos casos en los que la función no cambiará sus argumentos, pero en los que es deseable pasar una referencia (es decir, un puntero) a la variable en lugar de una copia de la variable. Esto ocurre cuando una variable grande, (una estructura o un objeto de alguna clase) se pasa como argumento.
Funciones que retornan Funciones que retornan referenciasreferencias
#include <iostream>#include <iomanip>using std::cout;using std::endl;using std::setw;double& lowest(double values[], int length); int main(void){double array[] = { 3.0, 10.0, 1.5, 15.0, 2.7, 23.0,4.5, 12.0, 6.8, 13.5, 2.1, 14.0 };//no puedo crear arrays de referenciasint len = sizeof array/sizeof array[0]; cout << endl;for(int i = 0; i < len; i++)
cout << setw(6) << array[i];lowest(array, len) = 6.9; // Change lowest to 6.9, cambia array[2]lowest(array, len) = 7.9; // Change lowest to 7.9,cambia array[10]cout << endl;//Raro lo anterior!,se puede hacer con * pero asífor(int i = 0; i < len; i++)//más sencillocout << setw(6) << array[i];cout << endl;return 0;}
Funciones que retornan Funciones que retornan referenciasreferencias
double& lowest(double a[], int len){int j = 0; // Index of lowest elementfor(int i = 1; i < len; i++)if(a[j] > a[i]) // Test for a lower value...j = i; // ...if so update jreturn a[j]; // Return reference to lowest// element//ídem a retornar un double, si hubiese retornado un puntero:&a[j];}
3 10 1.5 15 2.7 23 4.5 12 6.8 13.5 2.1 14 3 10 6.9 15 2.7 23 4.5 12 6.8 13.5 7.9 14Presione una tecla para continuar . . .//podría usar el valor de retorno del lado derecho del = //lowest(x, lenx) = 2.0*lowest(y, leny);//al igual que con punteros: nunca retornar referencias a variables locales
Referencias a objetos de Referencias a objetos de una claseuna clase
class Candado{int programado[3];int actual[3];};
public:
Candado(int []);
void alterardigito(int i, int nro);
bool puedeAbrir()const;
bool mismaCombinacionActual(const Candado &c)const;
~Candado(void);
bool Candado::mismaCombinacionActual(const Candado &c)const{
for(int i=0;i<3;i++)
if(actual[i]!=c.actual[i])
return false;
return true;}
Referencias a objetos de Referencias a objetos de una claseuna clase
int main(void){
int p1[]={3,2,1};
int p2[]={1,2,3};
Candado c1=Candado(p1);
Candado c2=Candado(p2);
if(c1.mismaCombinacionActual(c2))
cout<<"Los dos candados tienen la misma combinacion actual\n";
else
cout<<"Los dos candados no tienen la misma combinacion actual\n";
return 0;
}
Constructor de copiaConstructor de copiaclass CSimpleString{
size_t len;
char* buff;
public:
CSimpleString(const char* p = 0);
CSimpleString(const CSimpleString& s);// constructor copia
void print(){cout << buff;}
~CSimpleString();
};
CSimpleString::CSimpleString(const CSimpleString& s){
len = s.len;
buff = new char[len+1];
strcpy_s(buff, len+1, s.buff);}
Constructor de copiaConstructor de copiaint main(){
CSimpleString s1 = "hello";
CSimpleString s2 =s1;
cout << "s1 = \"";
s1.print();
cout << "\"" << endl;
cout << "s2 = \"";
s2.print();
cout << "\"" << endl;
return 0;}
Destructores y asignación Destructores y asignación dinámica de memoriadinámica de memoria
CSimpleString::CSimpleString(const char* p) : len(0), buff(0){
if (p != 0) {
len = strlen(p);
if (len > 0) {
buff = new char[len+1];
strcpy_s(buff, len+1, p);
} }}
CSimpleString::~CSimpleString()
{
delete []buff;
}
Destructores y asignación Destructores y asignación dinámica de memoriadinámica de memoria
Atleta::Atleta(char* n, int nro, char* p, double t){
nombre=new char[strlen(n) + 1];
strcpy(nombre, n);
numero=nro;
nacionalidad=new char[strlen(p)+1];
strcpy(nacionalidad, p);
tiempo=t;}
Atleta::~Atleta(void){
delete[] nombre;
delete[] nacionalidad;
cout<<"Se invoca al destructor de atleta\n";
}
Destructores y asignación Destructores y asignación dinámica de memoriadinámica de memoria
EsONoMagica::EsONoMagica(int **m, int f, int c){
filas=f;
columnas=c;
//reservo espacio para el vector que apunta a las filas
matriz=new int*[f];
//reservo memoria para las columnas de cada fila
for(int i=0;i<c;i++)
matriz[i]=new int[c];
//llena con datos
for(int i=0;i<filas;i++)
for(int j=0;j<columnas;j++)
matriz[i][j]=m[i][j];}
Destructores y asignación Destructores y asignación dinámica de memoriadinámica de memoria
EsONoMagica::~EsONoMagica(void)
{
//libera la memoria de la matriz
for(int i=0;i<filas;i++)
delete[]matriz[i];//libera columnas
delete[]matriz;//libera filas
}
Sobrecarga de operadoresSobrecarga de operadores
//uso referencia para evitar copia y const porque no modifica el objeto
bool Point3D::operator>(const Point3D& q) const {
return (this->distanceOrigin()>q. distanceOrigin());
}
Sobrecarga de operadoresSobrecarga de operadores
//debe retornar referencia por características de la asignación y asociatividad de derecha a izquierda (permite concatenar operaciones)
CSimpleString& CSimpleString::operator=(const CSimpleString& rhs){
len = rhs.len;//operación modifica operando izquierdo
delete buff;//primero borra memoria asignada
buff = new char[len+1];//ahora copia
strcpy_s(buff, len+1, rhs.buff);//objeto invocador el del lado izqq.del =
return *this;}//retorna resultado operación en el mismo objeto,
//A.operator=(B); o A=B;
//por si hago A=A; debería en 1º lugar hacer:
if(this==&rhs)//chequea direcciones y si son iguales
return *this;//retorna primer operando
Sobrecarga de operadoresSobrecarga de operadoresint main(){
CSimpleString s1 = "hello";
CSimpleString s2 = "goodbye";
cout << " After executing s2 = s1:" << endl;
s2 = s1;
cout << "s1 = \"";
s1.print();
cout << "\"" << endl;
cout << "s2 = \"";
s2.print();
cout << "\"" << endl;
return 0;
}
Sobrecarga de operadoresSobrecarga de operadoresCSimpleString CSimpleString::operator+(const CSimpleString& s)
{
size_t length = len + s.len + 1;
char* tmp = new char[length];
strcpy_s(tmp, length, buff);
strcat_s(tmp, length, s.buff);
return CSimpleString(tmp);
}
Sobrecarga de operadoresSobrecarga de operadores
CSimpleString::CSimpleString(const char* p) : len(0), buff(0){
if (p != 0){
len = strlen(p);
if (len > 0){
buff = new char[len+1];
strcpy_s(buff, len+1, p);
}}}
// Addition operator: CSimpleString object + string constant
CSimpleString CSimpleString::operator+(const char* s){
return *this + CSimpleString(s);}
Sobrecarga de operadoresSobrecarga de operadores// += operator
CSimpleString& CSimpleString::operator+=(const CSimpleString& rhs){
*this = *this + rhs;//usa los operadores + e =
return *this;
}
int main(){
CSimpleString s1 = "hello";
s1 += " world!";
cout << "s1 = \"";
s1.print();
cout << "\"" << endl;
return 0;}