13.01.2015 Views

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

SHOW MORE
SHOW LESS

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 />

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!