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

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

✐<br />

✐<br />

✐<br />

“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 218 — #256<br />

✐<br />

Capítulo 7. Sobrecarga de funciones y argum<strong>en</strong>tos por defecto<br />

s2.print(cout);<br />

} ///:~<br />

Todo lo que puede hacer con esta clase es crear un MyString, concat<strong>en</strong>ar texto<br />

e imprimir a un ostream. La clase sólo conti<strong>en</strong>e un puntero a un Mem, pero note<br />

la difer<strong>en</strong>cia <strong>en</strong>tre el constructor por defecto, que pone el puntero a cero, y el segundo<br />

constructor, que crea un Mem y copia los datos d<strong>en</strong>tro del mismo. La v<strong>en</strong>taja<br />

del constructor por defecto es que puede crear, por ejemplo, un array grande de objetos<br />

MyString vacíos con pocos recursos, pues el tamaño de cada objeto es sólo<br />

un puntero y la única sobrecarga <strong>en</strong> el r<strong>en</strong>dimi<strong>en</strong>to del constructor por defecto es<br />

el de asignarlo a cero. El coste de un MyString sólo empieza a aum<strong>en</strong>tar cuando<br />

concat<strong>en</strong>a datos; <strong>en</strong> ese mom<strong>en</strong>to el objeto Mem se crea si no ha sido creado todavía.<br />

Sin embargo, si utiliza el constructor por defecto y nunca concat<strong>en</strong>a ningún dato, la<br />

llamada al destructor todavía es segura porque cuando se llama a delete con un<br />

puntero a cero, el compilador no hace nada para no causar problemas.<br />

Si mira los dos constructores, <strong>en</strong> principio, podría parecer que son candidatos para<br />

utilizar argum<strong>en</strong>tos por defecto. Sin embargo, si elimina el constructor por defecto<br />

y escribe el constructor que queda con un argum<strong>en</strong>to por defecto:<br />

MyString(char* str = "");<br />

todo funcionará correctam<strong>en</strong>te, pero perderá la eficacia anterior pues siempre se<br />

creará el objeto Mem. Para volver a t<strong>en</strong>er la misma eficacia de antes, ha de modificar<br />

el constructor:<br />

MyString::MyString(char* str) {<br />

if (!*str) { // Apunta a un string ívaco<br />

buf = 0;<br />

return;<br />

}<br />

buf = new Mem(strl<strong>en</strong>(str) + 1);<br />

strcpy((char*)buf->pointer(), str);<br />

}<br />

Esto significa, <strong>en</strong> efecto, que el valor por defecto es un caso que ha de tratarse separadam<strong>en</strong>te<br />

de un valor que no lo es. Aunque parece algo inoc<strong>en</strong>te con un pequeño<br />

constructor como éste, <strong>en</strong> g<strong>en</strong>eral esta práctica puede causar problemas. Si ti<strong>en</strong>e que<br />

tratar por separado el valor por defecto <strong>en</strong> vez de tratarlo como un valor ordinario,<br />

debería ser una pista para que al final se implem<strong>en</strong>t<strong>en</strong> dos funciones difer<strong>en</strong>tes d<strong>en</strong>tro<br />

de una función: una versión para el caso normal y otra para el caso por defecto.<br />

Podría partirlo <strong>en</strong> dos cuerpos de función difer<strong>en</strong>tes y dejar que el compilador elija.<br />

Esto resulta <strong>en</strong> un ligero (pero normalm<strong>en</strong>te invisible) increm<strong>en</strong>to de la eficacia porque<br />

el argum<strong>en</strong>to extra no se pasa y por tanto el código extra debido a la condición<br />

condición no se ejecuta. Más importante es que está mant<strong>en</strong>i<strong>en</strong>do el código <strong>en</strong> dos<br />

funciones separadas <strong>en</strong> vez de combinarlas <strong>en</strong> una utilizando argum<strong>en</strong>tos por defecto,<br />

lo que resultará <strong>en</strong> un mant<strong>en</strong>imi<strong>en</strong>to más s<strong>en</strong>cillo, sobre todo si las funciones<br />

son largas.<br />

Por otro lado, considere la clase Mem. Si mira las definiciones de los dos constructores<br />

y las dos funciones pointer(), puede ver que la utilización de argum<strong>en</strong>tos<br />

por defecto <strong>en</strong> ambos casos no causará que los métodos cambi<strong>en</strong>. Así, la clase podría<br />

ser fácilm<strong>en</strong>te:<br />

218<br />

✐<br />

✐<br />

✐<br />

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

Saved successfully!

Ooh no, something went wrong!