clases y objetos en c++ · a objetos y, en particular, para especificar argumentos de funciones y...
TRANSCRIPT
![Page 1: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/1.jpg)
Clases y objetos en C++ Segunda parte
![Page 2: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/2.jpg)
Funciones miembros const
Para hacer el puntero this const en
una función miembro, debe declararlo
dentro de la definición de la clase
Dentro de la clase Vagon
int compare(Vagon v) const
{
return this->Volumen()>
v.Volumen();
}
![Page 3: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/3.jpg)
Funciones miembros const
Para especificar que una función miembro es const, se añade la palabra clave const al final de la cabecera de la función
El hacer el puntero this const, significa que no puede figurar ningún dato miembro en el lado izquierdo de una asignación, caso contrario será indicado como un error por el compilador
Una función const no puede invocar una función no const de la misma clase puesto que, podría modificar el objeto con el cual se invoca la función
![Page 4: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/4.jpg)
Funciones miembros const
Cuando una función miembro const se define fuera de la clase, el encabezado de la definición de la función debe añadir la palabra const, tal como se lo hace en el prototipo de dicha función dentro de la clase.
Sino se lo hace, el código no compila. Una función con el modificador const es diferente a una función sin este modificador. Muchas veces es útil tener una versión const y una versión sobrecargada no const
![Page 5: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/5.jpg)
Arrays de objetos
Se puede declarar un array de objetos de
una clase, de la misma forma en que se lo
hace con un array de tipos de datos
primitivos
Cada elemento de un array de objetos
provoca que el constructor por defecto
sea invocado. Importante que la clase
tenga uno (si es que tiene por lo menos
un constructor)
![Page 6: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/6.jpg)
Arrays de objetos
Vagon vagones[5];
Esta declaración implica que se invoque 5 veces
el constructor por defecto (no arg)
Todos los constructores (sobrecargados)
tendrán todos distintos argumentos así que, el
compilador no detectará ninguna ambigüedad
Vagon (){
alto = ancho = longitud = 1.0;
}
![Page 7: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/7.jpg)
Punteros a objetos de una clase
El uso de punteros a objetos es muy
importante en la programación orientada
a objetos y, en particular, para especificar
argumentos de funciones y para retornar
de las mismas, por eficiencia en uso de
memoria y de tiempo insumido en
generar copias de los objetos
Se declara de la misma forma que
cualquier puntero
![Page 8: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/8.jpg)
Punteros a objetos de una clase
Por ejemplo, Vagon *pv=0;
pv=&unVagon;
Como con el puntero this para, invocar
una función miembro o, dentro de una de
la definición de una de ellas, acceder a un
campo, uso el operador ->
cout<<pv->Volumen()<<endl;
![Page 9: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/9.jpg)
Punteros a objetos de una clase
//comparo dos vagones por su volumen
int Vagon::compare (Vagon* pv) const
{
return this->Volumen() > pv- >Volumen();
}
![Page 10: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/10.jpg)
Punteros a objetos de una clase Vagon* pv1=&unVagon; Vagon* pv2=&otroVagon; Vagon vagones[5] … if(pv2->compare(pv1)) cout<<“otroVagon es mayor que unVagon\n”; pv1=vagones; vagones[2]=otroVagon; cout<<“Volumen de vagones[2]= “<<(pv1+2)->Volumen()<<endl;
![Page 11: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/11.jpg)
Referencias en C++
![Page 12: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/12.jpg)
Referencias
Una referencia es un alias de otra variable
y puede utilizarse en lugar del nombre de
la variable de la cual es un alias.
Debido a que no es un puntero, la
variable de la cual es un alias, debe
especificarse cuando se declara la
referencia y, a diferencia de un puntero,
no puede alterarse para representar otra
variable
![Page 13: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/13.jpg)
Referencias
long number=0;
long& rnumber=number;
rnumber+=10; //number=10
Con punteros
long *pnumber=&number;
*pnumber+=10;//desreferencio
![Page 14: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/14.jpg)
Referencias a objetos de una clase
Al igual que con los punteros, no hay
diferencias al declarar y usar una
referencia a objetos de una clase y una a
tipo de datos primitivos
Vagon& rv=unVagon;
cout<<rv.Volumen()<<endl;
![Page 15: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/15.jpg)
Constructor de copia
![Page 16: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/16.jpg)
Constructor de copia
La importancia de las referencias a objetos de una clase, está realmente en el contexto de argumentos y valores de retorno de funciones
El constructor de copia es un constructor que crea un objeto inicializándolo con otro objeto existente de la misma clase
Se podría escribir el prototipo dentro de la definición de una clase, como
Vagon(Vagon v);
![Page 17: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/17.jpg)
Constructor de copia
Si se escribe la declaración
Vagon v2=unVagon; Genera una llamada al constructor de copia
de la siguiente forma Vagon::Vagon(unVagon)
Esto no parece presentar problemas hasta que, se ve que los argumentos se pasan por valor (copia), es decir el compilador tiene que generar una copia de unVagon, para ello llamará al constructor de copia! Y así en forma recursiva, terminando con un número infinito de llamadas al constructor de copia
![Page 18: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/18.jpg)
Constructor de copia
La solución es usar una referencia const como argumento
Vagon (const Vagon& v);
Ahora el argumento del constructor no necesita copiarse, sólo debe inicializarse el argumento tipo referencia con el objeto a copiar.
El calificador const asegura que el argumento no puede modificarse dentro de la función
![Page 19: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/19.jpg)
Constructor de copia
Siempre declare un argumento de tipo referencia como const, a menos que la función deba modificar dicho argumento
Se puede implementar el constructor de copia como Vagon::Vagon(const Vagon& v){ alto=v.alto; ancho=v.alto; longitud=v.longitud; }
Igualmente podría usarse el formato de lista de inicialización para establecer los valores de los campos
![Page 20: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/20.jpg)
Constructor de copia
![Page 21: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/21.jpg)
Constructor de copia
![Page 22: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/22.jpg)
Ejemplo
La salida por pantalla al ejecutar main
Se invoca 2 veces al destructor, delete borra la memoria asignada por new, en este caso, la memoria apuntada por pM; debido a que pM apunta a un objeto CMessage (que tiene definido un destructor), delete además invoca al destructor de esta clase para liberar el espacio en memoria reservada para algunos campos
![Page 23: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/23.jpg)
Constructor de copia
Cuando en una clase se asigna memoria
dinámicamente para algún campo el
constructor de copia por defecto no es
adecuado, por ejemplo
![Page 24: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/24.jpg)
Constructor de copia
El efecto del constructor de copia por
defecto será copiar la dirección
almacenada en el puntero miembro
(pmessage) desde motto1 a motto2,
con lo cual lograremos tener un string
compartido por dos objetos
![Page 25: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/25.jpg)
![Page 26: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/26.jpg)
Constructor de copia
Si el string compartido se cambia en uno
de los objetos, también cambiará en el
otro
Si se destruye motto1 (o a la inversa), el
puntero pmessage de motto2 quedará
apuntando a un área de memoria que fue
liberada y, si se utiliza posteriormente,
puede ocurrir un desastre!
![Page 27: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/27.jpg)
Constructor de copia Lo mismo ocurrirá con una función que tome
como argumento un objeto de tipo CMessage.
El argumento es local (paso por valor, se genera
1 copia con el constructor de copia por
defecto) a esta función y cuando se termine de
ejecutar, el destructor se invoca y se borra el
área de memoria apuntada por pmessage (en la
copia y en objeto original este puntero apuntan
al mismo string)
![Page 28: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/28.jpg)
Constructor de copia
En el ejemplo, el puntero pmessage en el objeto que se pasa a la función (thought) aún apunta a un área de memoria que se borró.
La próxima vez que se intente usar dicho objeto (o aún cuando no lo use nunca ya que en algún momento, por ejemplo al terminar de ejecutar main, deberá borrarlo), el programa se puede comportar de formas extrañas
![Page 29: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/29.jpg)
Constructor de copia
Moraleja: Si se asigna memoria
dinámicamente para algún campo de una
clase, implemente un constructor de
copia
![Page 30: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/30.jpg)
Sigamos sobrecargando operadores
Trabajando con el ejemplo original que
trabaja con contenedores(cajas) tipo
prismas rectangulares (libro Ivor
Horton`s Beginning Visual C++ 2008
![Page 31: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/31.jpg)
Sobrecarga de operadores
![Page 32: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/32.jpg)
Soporte completo a la comparación
Con este operador hay cosas que no puedo hacer
El operador sobrecargado, no servirá para esta operación, se producirá un error al compilar, para ello es necesario escribir otra versión del operador >.
Recordar que el argumento que se le pasa corresponde al operando derecho de >, el operando izquierdo será definido implícitamente por el puntero this
![Page 33: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/33.jpg)
Soporte completo a la comparación
El operador resulta
Pero, para una sentencia como,
Se puede pensar que lo resolvería sobrecargando el operador < que, acepte un operando (argumento) derecho de tipo double y reescribir la sentencia del if
![Page 34: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/34.jpg)
Soporte completo a la comparación
Pero, el uso de los objetos debería ser tan natural como posible, no se debería artificialmente restringir las formas en las cuales se usan los objetos en una expresión.
Un operador binario sobrecargado siempre provee el operando izquierdo mediante el puntero this.
Con lo cual tenemos 2 opciones para resolver este problema: usar una función ordinaria o usar una función friend
![Page 35: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/35.jpg)
Soporte completo a la comparación
Debido a que, en el operador no se accede
directamente a los campos privados (se usa
Volume(), declarada public) no se
necesita una función friend, de forma tal
que, se usará una función ordinaria, con lo
cual, el prototipo debe estar fuera de la
definición de la clase (por ejemplo, luego de
la definición de la clase, nunca antes de ella,
salvo que se use una declaración de clase
incompleta antes del prototipo)
![Page 36: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/36.jpg)
![Page 37: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/37.jpg)
Sobrecarga del operador de
asignación Sino se lo provee, el compilador suministra
uno por defecto, simplemente hace una copia miembro por miembro, similar a lo que ocurre con el constructor de copia por defecto.
Sin embargo, ambos no deben confundirse. El primero se invoca cuando se encuentra una asignación (no inicialización) donde ambos operandos del = son objetos del mismo tipo
Para la clase CBox este operador de asignación por defecto funciona sin problemas
![Page 38: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/38.jpg)
Sobrecarga del operador de
asignación Pero, para el caso de clases con campos
que asignan memoria dinámicamente, al
igual que con el constructor de copia,
este operador de = puede traer
problemas.
Volviendo a la clase CMessage, si se usa
el operador de asignación por defecto
![Page 39: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/39.jpg)
Sobrecarga del operador de
asignación El efecto es esencialmente el mismo que
para el constructor de copia por defecto, nuevamente tenemos un puntero pmessage al mismo string
Se necesita crear un operador de asignación, que copie el texto apuntado por pmessage del objeto que se pasa como argumento, al área de memoria propiedad del objeto que está del lado izquierdo
![Page 40: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/40.jpg)
Sobrecarga del operador de
asignación
![Page 41: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/41.jpg)
Sobrecarga del operador de
asignación La operación de asignación es muy simple
pero, hay algunas sutilezas que necesitan
investigarse.
El operador retorna una referencia, para
visualizar el motivo: es probable que el
resultado de la asignación, a su vez,
necesite usarse en el lado derecho de
otra asignación
![Page 42: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/42.jpg)
Sobrecarga del operador de
asignación Debido a que, el operador asignación es
asociativo por derecha, la operación se realiza en este orden (primero se asigna motto2=motto3)
La llamada al operator=() que está entre paréntesis, debe retornar un objeto de tipo CMessage que, pueda usarse como argumento del otro operator=(), con lo cual, el tipo de retorno podría ser de tipo CMessage o CMessage&,con lo cual en este caso no es obligatorio retornar una referencia
![Page 43: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/43.jpg)
Sobrecarga del operador de
asignación Sin embargo, considere el siguiente
ejemplo, donde se usan ( ), para forzar
que la asignación dentro de ellos se
realice primero:
Esto se traslada a
![Page 44: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/44.jpg)
Sobrecarga del operador de
asignación Ahora se tiene una situación donde, el objeto
retornado por el operator=() (motto1=motto2) se usa del lado izquierdo del otro operator=(),
si elijo usar como tipo de retorno del operador de asignación a CMessage (en lugar de una referencia), esto no es legal debido a que se generará una copia temporal del objeto retornado y, el compilador no permitirá que use esta copia temporal (no es un lvalue) para invocar una función miembro (en este caso operator=).
![Page 45: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/45.jpg)
Sobrecarga del operador de
asignación La única forma en que el código compile es
retornar una CMessage& (es un lvalue),
único tipo posible de retorno para permitir
un uso completamente flexible del operador
de asignación
Aquí se ve la utilidad del puntero this ya
que, se necesita devolver una referencia al
objeto apuntado por this (objeto con el
cual se invoca al operador, operando
izquierdo de =), por eso se retorna *this
![Page 46: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/46.jpg)
Sobrecarga del operador de
asignación La 2º sutileza a tener en cuenta es que, cada
objeto ya tiene asignada memoria dinámicamente para alojar un string, de forma tal que,
lo 1º que se hace en un operador de asignación en estos casos, es borrar el espacio de memoria reservado para el 1º objeto (lado izquierdo del =) y, reasignar suficiente memoria para alojar el string perteneciente al 2º objeto (lado derecho del =).
Una vez hecho esto, el string del objeto a copiar, se copia al nuevo espacio de memoria ahora propiedad del objeto que está del lado izquierdo de la asignación (apuntado por this)
![Page 47: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/47.jpg)
Sobrecarga del operador de
asignación Pero, hay un defecto en esta
implementación del operador =
¿Qué ocurre si se tiene algo como esto?
Muy probablemente el intento de auto
asignación quede enmascarado detrás de
un puntero que apunte a motto1
![Page 48: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/48.jpg)
Sobrecarga del operador de
asignación En este caso, el operador = borra la
memoria asignada al string contenido en motto1, e intenta reservar memoria basada en la longitud de dicho string que se borró y copiar la vieja memoria asignada (ya no existe) que puede estar corrompida
Para evitar esto, simplemente, al principio del operador de asignación se chequea que sean distintos los 2 operandos de =
![Page 49: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/49.jpg)
Sobrecarga del operador de
asignación
![Page 50: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/50.jpg)
Sobrecarga de operador de
asignación Moraleja: Implemente el operador de
asignación siempre que la clase tenga
campos que reserven memoria
dinámicamente
![Page 51: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/51.jpg)
Sobrecarga del operador suma
En el caso de la clase CBox la suma debe retornar un nuevo objeto CBox que será la suma, sea lo que sea que signifique, de los 2 operandos (2 objetos de tipo CBox).
¿Qué significará sumar 2 objetos de esta clase? En este ejemplo se consideró que la suma devolverá un objeto CBox que sea capaz de contener lo mismo que los dos contenedores sumados, uno encima del otro
![Page 52: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/52.jpg)
Sobrecarga del operador suma
![Page 53: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/53.jpg)
Sobrecarga del operador suma
En la declaración del operador suma, hay que suministrarle los dos operandos
Se pasa como argumento una referencia para evitar la copia innecesaria del operando derecho de la suma y,
se declara const a dicha referencia para indicar que la función no modificará el argumento y que, se permitirá tener un operando derecho que sea const,
también se declara const al operador ya que no modificará el objeto con el cual se lo invocará (operando izquierdo de la suma)
![Page 54: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/54.jpg)
Sobrecarga del operador suma
![Page 55: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/55.jpg)
Sobrecarga del operador suma
Se construye un objeto local a
partir del objeto con el cual se invoca, el
operando izquierdo de la suma (*this) y
el objeto que se pasa como argumento
(operando derecho de la suma), aBox.
Recuerde que así como está definida la
función, retorna una copia temporal del
objeto local creado. El objeto local se
descarta cuando la función retorna
![Page 56: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/56.jpg)
Sobrecarga del operador suma
Se modifica el constructor para
asegurarse que el valor del campo que
almacena la longitud del contenedor no
sea menor (pueden ser iguales) que el
valor del campo que contiene el ancho
del mismo
![Page 57: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/57.jpg)
Sobrecarga del operador suma
Se añade además una función para
mostrar las dimensiones de un objeto
Cbox; con la misma se podrá verificar que,
la versión sobrecargada del operador
suma funciona correctamente
Si sumamos, por ejemplo 3 objetos, el
operador se llamará 2 veces
![Page 58: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/58.jpg)
Sobrecarga del operador suma
La salida por pantalla será:
![Page 59: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/59.jpg)
Sobrecarga del operador suma
También podría haberse definido el
operador suma usando una función
friend y se usará el operador . para
acceder a los campos de los dos objetos
pasados como argumentos.
![Page 60: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/60.jpg)
Sobrecarga de los operadores ++ y
-- Estos operadores tienen algunas
características que los distinguen de los
otros
Ambos operadores tienen dos formas:
prefija y postfija y, el efecto es diferente
según se use una forma u otra
Utilizaremos una clase muy simple con un
campo double que representa una
longitud
![Page 61: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/61.jpg)
Sobrecarga de los operadores ++ y
-- Para poder diferenciar las 2 versiones del
mismo operador, se lo hace usando
distintos argumentos.
La forma prefija no toma argumentos y, la
forma postfija, toma un argumento de tipo
int que, no se usa en la implementación,
sólo sirve para distinguir las 2 versiones
![Page 62: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/62.jpg)
Versión prefija
En esta versión el operando se
incrementa o decrementa en 1, antes de
que su valor se use en una expresión,
retornando una referencia al objeto actual
(con el cual se invoca, único operando)
luego de incrementarlo o decrementarlo
![Page 63: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/63.jpg)
Versión postfija En esta versión, el único operando es
incrementado o decrementado en 1,luego que el mismo es usado en una expresión. Esto se logra creando un nuevo objeto, copia del objeto original pasado como argumento, antes de proceder a incrementar el objeto actual, retornando la copia del objeto original sin incrementar, después de modificar el objeto actual
Declarar el valor de retorno como const previene que expresiones como data++++ compilen
![Page 64: Clases y objetos en C++ · a objetos y, en particular, para especificar argumentos de funciones y para retornar de las mismas, por eficiencia en uso de memoria y de tiempo insumido](https://reader033.vdocuments.co/reader033/viewer/2022050513/5f9d63bc54ff5178e664472e/html5/thumbnails/64.jpg)
Sobrecarga de los operadores ++ y
--