Miembros estáticos de una clase/estructura

Miembros estáticos

Los miembros de una clase pueden ser declarados con el uso del modificador de la clase de memoria static. Estos miembros de datos se comparten por todos los ejemplares de esta clase y se guardan en un sitio. Los miembros de datos no estáticos se crean para cada variable-objeto de la clase.

La imposibilidad de declarar los miembros estáticos de una clase conduciría a la necesidad de declarar estos datos a nivel global del programa. Esto rompería las relaciones entre los datos y su clase, además de no concordarse con el paradigma básica de la POO - la unión de datos y métodos para su procesamiento dentro de una clase. El miembro estático permite existir a los datos de la clase que no son específicos para un ejemplar particular, en el campo de alcance de la clase.

Puesto que un miembro estático de la clase no depende de un ejemplar concreto, la referencia a él es como sigue:

class_name::variable

donde class_name es el nombre de la clase, y variable significa el nombre del miembro de la clase.

Como ve, para acceder al miembro estático de la clase, se utiliza el operador de resolución de contexto ::. Cuando accedemos a un miembro estático dentro de los métodos de la clase, el operador de contexto es opcional.

El miembro estático de la clase debe ser inicializado explícitamente con un valor necesario. Para eso hay que declarar e inicializarlo a nivel global. El orden de la inicialización de los miembros estáticos va a corresponder al orden de su declaración a nivel global en el código fuente.

Por ejemplo, tenemos una clase CParser que se utiliza para el análisis sintáctico de textos, y necesitamos obtener el número total de palabras y símbolos procesados. Sólo hay que declarar los miembros necesarios de la clase como estáticos e inicializarlos a nivel global. Entonces, todos los ejemplares de la clase van a utilizar durante su trabajo los contadores comunes de palabras y símbolos.

//+------------------------------------------------------------------+
//|  Clase "Analizador de textos"                                      |
//+------------------------------------------------------------------+
class CParser
  {
public:
   static int        s_words;
   static int        s_symbols;
   //--- constructor y destructor
                     CParser(void);
                    ~CParser(void){};
  };
...
//--- inicialización de los miembros estáticos de la clase Parser a nivel global
int CParser::s_words=0;
int CParser::s_symbols=0;

Un miembro estático de la clase puede ser declarado con la palabra clave const. Estas constantes estáticas tienen que ser inicializadas a nivel global con la palabra clave const:

//+------------------------------------------------------------------+
//|  Clase "Pila" para almacenar los datos procesados                 |
//+------------------------------------------------------------------+
class CStack
  {
public:
                     CStack(void);
                    ~CStack(void){};
...
private:
   static const int  s_max_length; // capacidad máxima de la pila
  };
 
//--- inicialización de la constante estática de la clase CStack
const int CStack::s_max_length=1000;

Puntero this #

La palabra clave this denota un puntero declarado implícitamente a sí mismo — a un ejemplar concreto de la clase en contexto del cual se ejecuta el método. Se puede utilizarlo sólo en los métodos no estáticos de la clase. El puntero this es un miembro implícito no estático de cualquier clase.

En las funciones estáticas se puede acceder sólo a los miembros/métodos estáticos de la clase.

Métodos estáticos

En MQL5 se permite utilizar las funciones-miembros del tipo static. El modificador static debe ir antes del tipo de la función devuelto en la declaración dentro de la clase.

class CStack
  {
public:
   //--- constructor y destructor
                     CStack(void){};
                    ~CStack(void){};
   //--- capacidad máxima de la pila
   static int        Capacity();
private:
   int               m_length;     // número de elementos en la pila
   static const int  s_max_length; // capacidad máxima de la pila
  };
//+------------------------------------------------------------------+
//| Devuelve el número máximo de elementos para el almacenamiento en la pila|
//+------------------------------------------------------------------+
int CStack::Capacity(void)
  {
   return(s_max_length);
  }
//--- inicialización de la constante estática de la clase CStack
const int CStack::s_max_length=1000;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- declaramos la variable del tipo CStack
   CStack stack;
//--- llamamos al método estático del objeto
   Print("CStack.s_max_length=",stack.Capacity());
//--- también se puede llamar de esta manera, ya que el método es estático y no requiere la presencia del objeto
   Print("CStack.s_max_length=",CStack::Capacity());
  }

El método con modificador const se llama constante y no puede modificar los miembros implícitos de su clase. La declaración de las funciones constantes de la clase y los parámetros constantes se llama control de constancia (const-correctness). Gracias a este control se puede estar seguro de que el compilador va a controlar la constancia de valores de los objetos y mostrará error en la fase de compilación en caso de violación.

El modificador const se pone después de la lista de argumentos dentro de la declaración de la clase. La definición fuera de la clase también debe incluir el modificador const:

//+------------------------------------------------------------------+
//| Clase "Rectángulo"                                            |
//+------------------------------------------------------------------+
class CRectangle
  {
private:
   double            m_width;      // ancho  
   double            m_height;     // alto
public:
   //--- constructores y destructor
                     CRectangle(void):m_width(0),m_height(0){};
                     CRectangle(const double w,const double h):m_width(w),m_height(h){};
                    ~CRectangle(void){};
   //--- cálculo de la superficie
   double            Square(voidconst;
   static double     Square(const double w,const double h);// { return(w*h); }
  };
//+------------------------------------------------------------------+
//|  Devuelve la superficie del objeto "Rectángulo"                      |
//+------------------------------------------------------------------+
double CRectangle::Square(voidconst
  {
   return(Square(m_width,m_height));
  }
//+------------------------------------------------------------------+
//|  Devuelve el resultado de multiplicación de dos variables                         |
//+------------------------------------------------------------------+
static double CRectangle::Square(const double w,const double h)
  {
   return(w*h);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- creamos un rectángulo rect con los lados 5 y 6
   CRectangle rect(5,6);
//--- buscaremos la superficie del rectángulo utilizando el método constante
   PrintFormat("rect.Square()=%.2f",rect.Square());
//--- buscaremos el resultado de los números utilizando el método estático de la clase CRectangle
   PrintFormat("CRectangle::Square(2.0,1.5)=%f",CRectangle::Square(2.0,1.5));
  }

Como argumento adicional a favor del uso del control de constancia sirve el hecho de que el compilador en este caso genera una optimización especial. Por ejemplo, coloca el objeto constante en la memoria sólo para la lectura.

Una función estática no puede ser determinada con el modificador const, puesto que este modificador garantiza la constancia de los miembros del ejemplar cuando se llama a esta función. Pero, como ya hemos dicho antes, una función estática por definición no puede acceder a los miembros no estáticos de la clase.

Véase también

Variables estáticas, Variables, Enlaces. Modificador & y la palabra clave this