Destructores

En el capítulo sobre estructuras hablamos de los destructores (véase la sección sobre Constructores y destructores). Recapitulemos brevemente: un destructor es un método que se llama cuando se destruye un objeto. El destructor comparte el mismo nombre que la clase, pero va precedido de una tilde (~). Los destructores no devuelven valores y no tienen parámetros. Una clase sólo puede tener un destructor.

Incluso si la clase no tiene destructor o el destructor está vacío, el compilador realizará implícitamente la «recogida de basura» de los siguientes tipos de campos: cadenas, arrays dinámicos y objetos automáticos.

Normalmente, el destructor se coloca en la sección pública de la clase; sin embargo, en algunos casos específicos, el desarrollador puede moverlo a un grupo de miembros de private o protected. Un destructor privado o protegido no le permitirá declarar una variable automática de esta clase en el código. Sin embargo, más adelante veremos la creación dinámica de objetos , y para ellos, tal restricción podría tener sentido.

En particular, algunos objetos pueden implementarse de forma que deban borrarse a sí mismos cuando ya no se necesiten (el concepto de determinación de la demanda puede ser diferente). En otras palabras: mientras los objetos son utilizados por cualquier parte del programa, dichos objetos existen, y tan pronto como se completa la tarea, se autodestruyen (un destructor privado deja la posibilidad de eliminar el objeto de los métodos de la clase).

Para los programadores experimentados de C++, vale la pena señalar que los destructores son siempre virtuales en MQL5 (obtendrá más información acerca de los métodos virtuales en la sección sobre Métodos virtuales (virtual y override)). Este factor no afecta a la sintaxis de la descripción.

En el ejemplo del programa de dibujo, técnicamente, un destructor puede no ser necesario para las formas. Sin embargo, con el fin de trazar la secuencia de llamadas a constructores y destructores, incluiremos uno. Empecemos con un esquema simplificado que «imprima» el nombre completo del método:

class Shape
{
   ...
   ~Shape()
   {
      Print(__FUNCSIG__);
   }
};

Pronto añadiremos este y otros métodos para poder distinguir una instancia de un objeto de otra.

Veamos el siguiente ejemplo. Un par de objetos Shape se describen en dos contextos diferentes: global (fuera de las funciones) y local (dentro de OnStart). Se llamará al constructor del objeto global una vez cargado el script y antes de llamar a OnStart , y se llamará al destructor antes de que se descargue el script. Se llamará al constructor del objeto local en la línea con la definición de la variable, y el destructor se llamará cuando el bloque de código que contiene la definición de la variable salga, en este caso la función OnStart.

// the global constructor and destructor are related to script loading and unloading
Shape global;
 
// object reference does not create a copy and does not affect lifetime
void ProcessShape(Shape &shape)
{
   // ...
}
 
void OnStart()
{
   // ...
   Shape local// <- local constructor call
   // ...
   ProcessShape(local);
   // ...
// <- local destructor call

Pasar un objeto por referencia a otras funciones no crea copias del mismo y no llama al constructor ni al destructor.