[C con Clase] Ahora el destructor

Steven Davidson steven en conclase.net
Mie Jun 20 09:36:26 CEST 2007


Hola Rodolfo,

El pasado 2007-06-20 03:20:27, rodolfo escribió:

r> Hola Steven y Programante,
r> Les agradezco muchisimo a los dos, he estado experimentando con lo que me 
r> dijeron, y ahora tengo las cosas mas claras, excepto por un punto que 
r> mencionaste Steven.
r> Intente invocar al constructor de copia como me dijiste (ya se que se 
r> autoinvoca por el compilador, pero queria probar) y no funciono esto :
r>    Cadena c33;
r>    c33.Cadena( c1.operator+(c2) );
r> Me sale un error que dice "Invalid use of class Cadena"

Esto es lógico, ya que no podemos invocar al constructor de esta manera. Lo que escribí no era para ser tomado literalmente; de hecho, mencioné que "se podría representar" de esta manera. En otras palabras, esto no es código C++ sino algo parecido para hacerte una idea.

Lo anterior sí podría reescribir para que sea código C++ aceptable; esto es,

Cadena c33( c1.operator+(c2) );

r> Otra cosa, en la rutina que mande en mi correo anterior, si es que el 
r> compilador estaba usando el constructor de copia, no puede haber sido el 
r> mio, porque yo tambien tenia un mensaje en el, para ver cuando era invocado. 
r> ¿ hay otro ?

Existen dos tipos de constructores por defecto:
1) Sin parámetros: Constructor()
2) Copia: Constructor( const Constructor & )

Si has creado tus propias "versiones" de estos constructores, entonces no hay otros por defecto. Ten presente que la asignación, mediante el operador =, también tiene su comportamiento por defecto entre variables de la misma estructura/clase.

Como dije en mi último correo-e, el compilador puede eliminar ciertos mecanismos para optimizar la instanciación. Escribiste:

Cadena c33 = c1 + c2;

Se debería instanciar un objeto 'Cadena' dentro de la operación + para luego ser copiado a otro objeto temporal que se instancia debido al valor de retorno del operador sobrecargado +. Este objeto temporal sirve ahora como base al constructor copia para instanciar el objeto 'c33'.

El compilador prevé que se instancia mucho y se destruye casi de inmediato para luego instanciar otra vez y destruir una vez más, hasta llegar al "final" cuando volvemos a instanciar por una tercera vez. Por lo tanto, existen muchas instanciaciones que malgastarían tiempo y memoria sin aportar mucho más.

Al final, el compilador decide "ligar", por así decirlo, las instanciaciones que sí valen la pena quedarse. De esta manera, nos libramos de hacer operaciones costosas y superfluas.

Lo que podrías hacer es mostrar la dirección de memoria del objeto a copiar pasado como parámetro al constructor copia. Por ejemplo,

Cadena::Cadena( const Cadena & ref )
{
  cout << "Constructor Copia: " << &ref << endl;
  ...
}

Así podrías seguir la pista a las instanciaciones.

r> Y por último, intente esto, y funciono, pero...:
r>   const Cadena c31 = c1.operator+(c2);
r>   Cadena c33 = Cadena::Cadena( c31 );
r> Si se supone que el constructor de copia no devuelve nada  como entonces 
r> puedo asignarlo a c33

Sí devuelve: el objeto en sí. Para eso sirve el constructor. Por ejemplo, podemos hacer lo siguiente si quisiéramos:

(Cadena( "Soy una cadena" ) + ". Y yo, otra").Mostrar();


Por cierto, sugiero modificar el prototipo para el operador +. En estos momentos, tienes escrito:

class Cadena
{
  ...
  const Cadena operator+( const Cadena &derecha );
};

Sugiero quitar 'const' y colocarlo al final del prototipo para crear una función constante. Con esto, indicamos que el operador + no tiene intención alguna de modificar el estado de este objeto; es decir, sus datos miembros no cambiarán. Esto es,

class Cadena
{
  ...
  Cadena operator+( const Cadena &derecha ) const;
};


Espero que esto te ayude.

Steven


Más información sobre la lista de distribución Cconclase