Diferencia entre revisiones de «Destructores (Programación)»

Línea 66: Línea 66:
 
*[[Constructores (Programación)| Constructores (Programación)]]  
 
*[[Constructores (Programación)| Constructores (Programación)]]  
 
*[[Función (programación)|Función (programación)]]  
 
*[[Función (programación)|Función (programación)]]  
 +
*[[Funciones virtuales|Funciones virtuales]]
 
== Fuente==
 
== Fuente==
 
*http://c.conclase.net/curso/?cap=030
 
*http://c.conclase.net/curso/?cap=030

Revisión del 14:14 12 dic 2017

Destructores (Programación)
Información sobre la plantilla
Concepto:Son un tipo especial de función miembro, estrechamente relacionados con los constructores

Destructores (Programación). Son un tipo especial de función miembro, estrechamente relacionados con los constructores. Son también funciones que no devuelven nada (ni siquiera void). Tampoco aceptan ningún parámetro, ya que la destrucción de un objeto no acepta ningún tipo de opción o especificación particular y es idéntica para todos los objetos de la clase. Los destructores no pueden ser heredados, aunque una clase derivada puede llamar a los destructores de su superclase si no han sido declarados privados (son públicos o protegidos). Lo mismo que ocurre con los constructores, tampoco puede obtenerse su dirección, por lo que no es posible establecer punteros a este tipo de funciones.

La misión más común de los destructores es liberar la memoria asignada por los constructores, aunque también puede consistir en desasignar y/o liberar determinados recursos asignados por estos. Por ejemplo, cerrar un fichero; una línea de comunicación, o desbloquear un recurso compartido que hubiera sido bloqueado previamente por el constructor.

Los destructores son invocados automáticamente (de forma implícita) por el programa en multitud de ocasiones; de hecho es muy raro que sea necesario invocarlos explícitamente. Su misión es limpiar los miembros del objeto antes que el propio objeto se auto-destruya.

Declaración

Los destructores se distinguen porque tienen el mismo nombre que la clase a que pertenecen precedido por la tilde ~ para simbolizar su estrecha relación con los constructores que utilizan el mismo nombre (son el "complemento" de aquellos). Ejemplo:

class X {
 public:
 ~X();      // destructor de la clase X
};
...
X::~X() {    // definición (off-line) del destructor
 ...
}

Invocación

Los destructores son invocados automáticamente por el compilador, y es muy raro que sea necesario invocarlos explícitamente.

Invocación explícita de destructores

En caso necesario los destructores pueden ser invocados explícitamente de dos formas: indirectamente, mediante una llamada a delete o directamente utilizando el nombre cualificado completo.

Ejemplo

class X {...};    // X es una clase
...
{
  X obj1;            // L.4: objeto automático
  X* ptr = new(X)    // L.5: objeto persistente
  X* pt2 = &obj1;    // Ok: pt2 es puntero a obj1 de la clase X
  ...
  pt2–>X::~X();      // L.8: Ok: llamada legal del destructor
                     // pt2->~X();            L.9: Ok: variación sintáctica de la anterior
                     // obj1.~X();            L.10: Ok otra posibilidad análoga
  X::~X();           // L.11: Error: llamada ilegal al destructor [1]
  delete ptr;        // L.12: Ok. invocación implícita al destructor
}

Invocación implícita de destructores

Además de las posibles invocaciones explícitas, cuando una variable sale del ámbito para el que ha sido declarada, su destructor es invocado de forma implícita. Los destructores de las variables locales son invocados cuando el bloque en el que han sido declarados deja de estar activo. Por su parte, los destructores de las variables globales son invocados como parte del procedimiento de salida después de la función main.

Propiedades de los destructores

Cuando se tiene un destructor explícito, las sentencias del cuerpo se ejecutan antes que la destrucción de los miembros. A su vez, la invocación de los destructores de los miembros se realiza exactamente en orden inverso en que se realizó la invocación de los constructores correspondientes. La destrucción de los miembros estáticos se ejecuta después que la destrucción de los miembros no estáticos. Los destructores no pueden ser declarados const o volatile, aunque pueden ser invocados desde estos objetos. Tampoco pueden ser declarados static, lo que supondría poder invocarlos sin la existencia de un objeto que destruir.

Destructores virtuales

Como cualquier otra función miembro, los destructores pueden ser declarados virtual. El destructor de una clase derivada de otra cuyo destructor es virtual, también es virtual. La existencia de un destructor virtual permite que un objeto de una subclase pueda ser correctamente destruido por un puntero a su clase-base.

Ejemplo

class B {   // Superclase (polimórfica)
 ...
 virtual ~B(); // Destructor virtual
};
class D : public B {    // Subclase (deriva de B)
 ...
 ~D(); // destructor también virtual
};
void func() {
 B* ptr = new D;    // puntero a superclase asignado a objeto de subclase
 ...
 delete ptr;        // Ok: delete es necesario siempre que se usa new
} 

Los destructores y exit

Cuando se invoca exit desde un programa, no son invocados los destructores de ninguna variable local del ámbito actual. Las globales son destruidas en su orden normal.

Los destructores y abort

Cuando se invoca la función abort en cualquier punto de un programa no se invoca ningún destructor, ni aún para las variables de ámbito global.

Véase también

Fuente