Las soluciones a los ejercicios se pueden encontrar en el documento electrónico titulado «The Thinking in C++ Annotated Solution Guide», disponible por poco dinero en www.BruceEckel.com.
Cree una clase sencilla con un operador sobrecargado ++
. Intente
llamar a este operador en la forma prefija y postfija y vea qué clase de
advertencia obtiene del compilador.
Cree una clase sencilla que contenga un int
y sobrecargue
el operador +
como un método. Cree también un método
print()
que tome un
ostream&
como un argumento y lo imprima a
un ostream&
. Pruebe su clase para comprobar
que funciona correctamente.
Añada un operador binario -
al ejercicio 2 como un
método. Demuestre que puede usar sus objetos en expresiones complejas
como a + b -c
.
Añada un operador ++
y otro --
al ejercicio
2, ambos con las versiones prefijas y postfijas, tales que devuelvan
el objeto incrementado o decrementado. Asegúrese de que la versión
postfija devuelve el valor correcto.
Modifique los operadores de incremento y decremento del ejercicio 4
para que la versión prefija devuelva una referencia no const
y
la postfija devuelva un objeto const
. Muestre que funcionan
correctamente y explique porqué esto se puede hacer en la práctica.
Cambie la función print()
del ejercicio2 para que
use el operador sobrecargado <<
como en
IostreamOperatorOverloading.cpp
.
Modifique el ejercicio 3 para que los operadores +
y
-
no sean métodos. Demuestre que todavía funcionan
correctamente.
Añada el operador unario -
al ejercicio 2 y demuestre que
funciona correctamente.
Cree una clase que contenga un único private
char
. Sobrecargue los operadores de flujos de entrada/salida
<<
y >>
(como en
IostreamOperatorOverloading.cpp
) y pruébelos. Puede
probarlos con fstreams
,
stringstreams
y cin
y
cout
.
Determine el valor constante ficticio que su compilador pasa
a los operadores postfijos ++
y
--
.
Escriba una clase Number
que contenga un
double
y añada operadores sobrecargados para
+
, -
, *
, /
y la
asignación. Elija los valores de retorno para estas funciones para que
las expresiones se puedan encadenar y que sea eficiente.
Escriba una conversión automática de tipos operator int()
.
Modifique el ejercicio 11 para que use la optimización del valor de retorno, si todavía no lo ha hecho.
Cree una clase que contenga un puntero, y demuestre que si permite al
compilador sintetizar el operador =
el resultado de usar ese
operador serán punteros que estarán solapados en la misma ubicación de
memoria. Ahora arregle el problema definiendo su propio operador
=
y demuestre que corrige el solapamiento. Asegúrese que
comprueba la auto-asignación y que maneja el caso apropiadamente.
Escriba una clase llamada Bird
que contenga un
miembro string
y un static int
. En el
constructor por defecto, use el int
para generar
automáticamente un identificador que usted construya en el
string
junto con el nombre de la clase(Bird
#1
, Bird #2
, etc). Añada un operador
<;<
para flujos de salida para imprimir los objetos
Bird
-Escriba un operador de asignación
=
y un constructor de copia. En main()
verifique que todo funciona correctamente.
Escriba una clase llamada BirdHouse
que contenga un
objeto, un puntero y una referencia para la clase
Bird
del ejercicio 14. El constructor debería tomar
3 Birds
como argumentos. Añada un operador
<<
de flujo de salida para
BirdHouse
. Deshabilite el operador de asignación
=
y el constructor de copia. En main()
verifique que todo funciona correctamente.
Añada un miembro de datos int
a Bird
y a BirdHouse
en el ejercicio 15. Añada
operadores miembros +
, -
, *
y
/
que usen el miembro int
para realizar las
operaciones en los respectivos miembros. Verifique que funcionan.
Repita el ejercicio 16 usando operadores no miembro.
Añada un operador -
a SmartPointer.cpp
y a NestedSmartPointer.cpp
.
Modifique CopyingVsInitialization.cpp
para que
todos los constructores impriman un mensaje que explique qué está
pasando. Ahora verifique que las dos maneras de llamar al constructor de
copia (la de asignación y la de paréntesis) son equivalentes.
Intente crear un operador no miembro =
para una clase y vea qué clase
de mensaje del compilador recibe.
Cree una clase con un operador de asignación que tenga un segundo argumento, un
string
que tenga un valor por defecto que diga op =
call
. Cree una función que asigne un objeto de su clase a otro y muestre
que su operador de asignación es llamado correctamente.
En CopyingWithPointers.cpp
elimine el operador
=
en DogHouse
y muestre que el
operador =
sintetizado por el compilador copia
correctamente string
pero es simplemente un alias
del puntero Dog
.
En ReferenceCounting.cpp
añada un static
int
y un int
ordinario como atributos a
Dog
y a DogHouse
. En
todos los constructores para ambas clases, incremente el static
int
y asigne el resultado al int
ordinario para
mantener un seguimiento del número de objetos que están siendo
creados. Haga las modificaciones necesarias para que todas las
sentencias de impresión muestren los identificadores int
de los objetos involucrados.
Cree una clase que contenga un string
como
atributo. Inicialice el string
en el constructor,
pero no cree un constructor de copia o un operador =
. Haga
una segunda clase que tenga un atributo de su primera clase; no cree un
constructor de copia o un operador =
para esta clase
tampoco. Demuestre que el constructor de copia y el operador
=
son sintetizados correctamente por el compilador.
Combine las clases en OverloadingUnaryOperators.cpp
y en Integer.cpp
.
Modifique PointerToMemmberOperator.cpp
añadiendo
dos nuevas funciones miembro a Dog
que no tomen
argumentos y devuelvan void
. Cree y compruebe un operador
sobrecargado ->*
que funcione con sus dos nuevas funciones.
Añada un operador ->*
a
NestedSmartPointer.cpp
.
Cree dos clases, Apple
y
Orange
. En Apple
, cree un
constructor que tome una Orange
como
argumento. Cree una función que tome un Apple
y
llame a esa función con una una Orange
para
demostrar que funciona. Ahora haga explícito el constructor de
Apple
para demostrar que así se evita la
conversión automática de tipos. Modifique la llamada a su función para
que la la conversión se haga explícitamente y de ese modo, funcione.
Añada un operador global *
a
ReflexivityInOverloading.cpp
y demuestre que es
reflexivo.
Cree dos clases y un operador +
y las funciones de
conversión de tal manera que la adicción sea reflexiva para las dos
clases.
Arregle TypeConversionFanout.cpp
creando una
función explícita para realizar la conversión de tipo, en lugar de uno
de los operadores de conversión automáticos.
Escriba un código simple que use los operadores +
,
-
, *
, /
para
double
. Imagine cómo el compilador genera el codigo
ensamblador y mire el ensamblador que se genera en realidad para
descubrir y explicar qué está ocurriendo «bajo el capó».