Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
✐<br />
✐<br />
✐<br />
“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 316 — #354<br />
✐<br />
Capítulo 11. Las refer<strong>en</strong>cias y el constructor de copia<br />
destructor, lo cual decrem<strong>en</strong>ta objectCount, y por lo tanto el objectCount se<br />
pone a cero. La creación de h2 se realiza también mediante la copia bit a bit, así que<br />
tampoco se llama al constructor, y cuando h y h2 sal<strong>en</strong> de ámbito, sus destructores<br />
causan el valor negativo <strong>en</strong> objectCount.<br />
11.3.2. Construcción por copia<br />
El problema se produce debido a que el compilador hace una suposición sobre<br />
cómo crear un nuevo objeto a partir de de otro exist<strong>en</strong>te. Cuando se pasa un objeto por<br />
valor, se crea un nuevo objeto, que estará d<strong>en</strong>tro del ámbito de la función, a partir<br />
del objeto original exist<strong>en</strong>te fuera del ámbito de la función. Esto también se puede<br />
aplicar a m<strong>en</strong>udo cuando una función retorna un objeto. En la expresión<br />
HowMany h2 = f(h);<br />
h2, un objeto que no estaba creado anteriorm<strong>en</strong>te, se crea a partir del valor que<br />
retorna f(); por tanto también se crea un nuevo objeto a partir de otro exist<strong>en</strong>te.<br />
El compilador supone que la creación ha de hacerse con una copia bit a bit, lo<br />
que <strong>en</strong> muchos casos funciona bi<strong>en</strong>, pero <strong>en</strong> HowMany no funciona porque la inicialización<br />
va más allá de una simple copia. Otro ejemplo muy común ocurre cuando<br />
la clase conti<strong>en</strong>e punteros pues, ¿a qué deb<strong>en</strong> apuntar ¿debería copiar sólo los punteros<br />
o debería asignar memoria nueva y que apuntaran a ella<br />
Afortunadam<strong>en</strong>te, puede interv<strong>en</strong>ir <strong>en</strong> este proceso e impedir que el compilador<br />
haga una copia bit a bit. Se soluciona defini<strong>en</strong>do su propia función cuando el compilador<br />
necesite crear un nuevo objeto a partir de otro. Lógicam<strong>en</strong>te, está creando<br />
un nuevo objeto, por lo que esta función es un constructor, y el único argum<strong>en</strong>to del<br />
constructor ti<strong>en</strong>e que ver con el objeto del que se pret<strong>en</strong>de partir para crear el nuevo.<br />
Pero no puede pasar ese objeto por valor al constructor porque está int<strong>en</strong>tando<br />
definir la función que maneja el paso por valor, y, por otro lado, sintácticam<strong>en</strong>te no<br />
ti<strong>en</strong>e s<strong>en</strong>tido pasar un puntero porque, después de todo, está creando un objeto a<br />
partir de de otro. Aquí es cuando las refer<strong>en</strong>cias vi<strong>en</strong><strong>en</strong> al rescate, y puede utilizar la<br />
refer<strong>en</strong>cia del objeto orig<strong>en</strong>. Esta función se llama constructor de copia, que también se<br />
lo puede <strong>en</strong>contrar como X(X&), que es el constructor de copia de una clase llamada<br />
X.<br />
Si crea un constructor de copia, el compilador no realizará una copia bit a bit<br />
cuando cree un nuevo objeto a partir de otro. El compilador siempre llamará al constructor<br />
de copia. Si no crea el constructor de copia, el compilador int<strong>en</strong>tará hacer<br />
algo razonable, pero usted ti<strong>en</strong>e la opción de t<strong>en</strong>er control total del proceso.<br />
Ahora es posible solucionar el problema <strong>en</strong> HowMany.cpp:<br />
//: C11:HowMany2.cpp<br />
// The copy-constructor<br />
#include <br />
#include <br />
using namespace std;<br />
ofstream out("HowMany2.out");<br />
class HowMany2 {<br />
string name; // Object id<strong>en</strong>tifier<br />
static int objectCount;<br />
public:<br />
316<br />
✐<br />
✐<br />
✐<br />
✐