Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
Pensar en C++ (Volumen 1) - Grupo ARCO
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 />
✐