Diferencia entre revisiones de «Destructores (Programación)»
(Página creada con '<div align="justify">{{Definición|Nombre= Destructores (Programación) |imagen= |concepto= Son un tipo especial de función miembro, estrechamente relacionados con los construc...') |
|||
| Línea 1: | Línea 1: | ||
<div align="justify">{{Definición|Nombre= Destructores (Programación) |imagen= |concepto= Son un tipo especial de función miembro, estrechamente relacionados con los constructores}} | <div align="justify">{{Definición|Nombre= Destructores (Programación) |imagen= |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 (Programación)|constructores]. Son también [Función (programació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. | + | '''Destructores (Programación)'''. Son un tipo especial de función miembro, estrechamente relacionados con los [[Constructores (Programación)|constructores]]. Son también [[Función (programació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. | 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. | ||
| Línea 8: | Línea 8: | ||
==Declaración== | ==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: | + | 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 { | |
| − | class X { | ||
public: | public: | ||
~X(); // destructor de la clase X | ~X(); // destructor de la clase X | ||
| − | }; | + | }; |
| − | ... | + | ... |
| − | X::~X() { // definición (off-line) del destructor | + | X::~X() { // definición (off-line) del destructor |
... | ... | ||
| − | } | + | } |
== Invocación== | == Invocación== | ||
| − | Los destructores son invocados automáticamente por el [Compilador|compilador], y es muy raro que sea necesario invocarlos explícitamente. | + | Los destructores son invocados automáticamente por el [[Compilador|compilador]], y es muy raro que sea necesario invocarlos explícitamente. |
===Invocación explícita de destructores=== | ===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. | 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==== | ====Ejemplo==== | ||
| − | class X {...}; // X es una clase | + | class X {...}; // X es una clase |
| − | ... | + | ... |
| − | { | + | { |
X obj1; // L.4: objeto automático | X obj1; // L.4: objeto automático | ||
X* ptr = new(X) // L.5: objeto persistente | X* ptr = new(X) // L.5: objeto persistente | ||
| Línea 31: | Línea 30: | ||
... | ... | ||
pt2–>X::~X(); // L.8: Ok: llamada legal del destructor | pt2–>X::~X(); // L.8: Ok: llamada legal del destructor | ||
| − | // pt2->~X(); L.9: Ok: variación sintáctica de la anterior | + | // pt2->~X(); L.9: Ok: variación sintáctica de la anterior |
| − | // obj1.~X(); L.10: Ok otra posibilidad análoga | + | // obj1.~X(); L.10: Ok otra posibilidad análoga |
X::~X(); // L.11: Error: llamada ilegal al destructor [1] | X::~X(); // L.11: Error: llamada ilegal al destructor [1] | ||
delete ptr; // L.12: Ok. invocación implícita al destructor | delete ptr; // L.12: Ok. invocación implícita al destructor | ||
| − | } | + | } |
| − | |||
=== Invocación implícita de destructores=== | === 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. | 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== | == Propiedades de los destructores== | ||
| − | Cuando se tiene un destructor explícito, las [Sentencias (programación)|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. | + | Cuando se tiene un destructor explícito, las [[Sentencias (programación)|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. | 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== | == Destructores virtuales== | ||
| Línea 46: | Línea 44: | ||
La existencia de un destructor virtual permite que un objeto de una subclase pueda ser correctamente destruido por un puntero a su clase-base. | 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=== | ===Ejemplo=== | ||
| − | class B { // Superclase (polimórfica) | + | class B { // Superclase (polimórfica) |
... | ... | ||
virtual ~B(); // Destructor virtual | virtual ~B(); // Destructor virtual | ||
| − | }; | + | }; |
| − | + | class D : public B { // Subclase (deriva de B) | |
| − | class D : public B { // Subclase (deriva de B) | ||
... | ... | ||
~D(); // destructor también virtual | ~D(); // destructor también virtual | ||
| − | }; | + | }; |
| − | + | void func() { | |
| − | void func() { | ||
B* ptr = new D; // puntero a superclase asignado a objeto de subclase | B* ptr = new D; // puntero a superclase asignado a objeto de subclase | ||
... | ... | ||
delete ptr; // Ok: delete es necesario siempre que se usa new | delete ptr; // Ok: delete es necesario siempre que se usa new | ||
| − | } | + | } |
| − | |||
== Los destructores y exit== | == 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. | 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. | ||
| Línea 72: | Línea 67: | ||
*[[Función (programación)|Función (programación)]] | *[[Función (programación)|Función (programación)]] | ||
== Fuente== | == Fuente== | ||
| − | * | + | *http://c.conclase.net/curso/?cap=030 |
| − | * | + | *http://msdn.microsoft.com/es-es/library/1838wste.aspx |
| − | * | + | *http://msdn.microsoft.com/es-es/library/66x5fx1b%28v=vs.80%29.aspx |
| − | * | + | *http://msdn.microsoft.com/es-es/library/6t4fe76c.aspx |
[[Category:Lenguajes_de_programación]] [[Category:Programación]] | [[Category:Lenguajes_de_programación]] [[Category:Programación]] | ||
Revisión del 10:03 7 dic 2012
| ||||
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.
Sumario
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.