Membros Estáticos de uma Classe/Estrutura

Membros Estáticos

Os membros de uma classe podem ser declarados usando o modificador de classe de armazenamento static. Esses membros de dados são compartilhados por todos as instâncias desta classe e são armazenados em um lugar. Membros de dados não estáticos são criados para cada variável de objeto de classe.

A incapacidade de declarar membros estáticos de uma classe teria levado a necessidade de declarar estes dados no nível global do programa. Isso quebraria a relação entre os dados e a classe deles, e não seria consistente com o paradigma básico da OOP - juntar dados e métodos para manipulá-los em uma classe. O membro estático permite que dados de classe não específicos a uma particular instância existam no escopo da classe.

Desde que um membro de classe estática não dependa de uma particular instância, a referência a ele é como se segue:

class_name::variable

onde class_name é o nome da classe, e variable é o nome do membro da classe.

Como se vê, para acessar o membro estático de uma classe, o operador de resolução de contexto :: é usado. Ao acessar um membro estático de dentro de métodos da classe, o operador de contexto é opcional.

Membro estático de uma classe deve ser explicitamente inicializado com o valor desejado. Para isso, deve ser declarado e inicializado em escopo global. A sequência de inicialização dos membros estáticos corresponderá a sequência de sua declaração em escopo global.

Por exemplo, temos a classe CParser usado para separar o texto, e precisamos contar o número total de palavras e caracteres processados. Nós só precisamos declarar os membros de classe necessários como estáticos e inicializá-los no nível global. Então todas as instâncias da classe usarão um contador comum para palavras e caracteres.

//+------------------------------------------------------------------+
//| Classe "Analisador de Texto"                                     |
//+------------------------------------------------------------------+
class CParser
  {
public:
   static int        s_words;
   static int        s_symbols;
   //--- Construtor e destrutor
                     CParser(void);
                    ~CParser(void){};
  };
...
//--- Inicialização de membros estáticos da classe Parser no nível global
int CParser::s_words=0;
int CParser::s_symbols=0;

Um membro de classe estático pode ser declarado com a palavra-chave const. Tais constantes estáticas devem ser inicializadas no nível global com a palavra-chave const:

//+------------------------------------------------------------------+
//| Classe "Stack" para armazenar dados processados                  |
//+------------------------------------------------------------------+
class CStack
  {
public:
                     CStack(void);
                    ~CStack(void){};
...
private:
   static const int  s_max_length; // Capacidade máxima da pilha
  };
 
//--- Inicialização da constante estática da classe CStack
const int CStack::s_max_length=1000;

Ponteiro this #

A palavra-chave this denota um ponteiro implicitamente declarado para si mesmo — para uma instância específica da classe, no contexto do qual o método é executado. Pode ser usado somente em métodos não estáticos da classe. O ponteiro this é um membro não estático implícito de qualquer classe.

Em funções estáticas você pode acessar somente membros/métodos estáticos de uma classe.

Métodos Estáticos

Em MQL5, funções membro do tipo estático podem ser usadas. O modificador static deve preceder o tipo do retorno de uma função na declaração dentro de uma classe.

class CStack
  {
public:
   //--- Construtor e destrutor
                     CStack(void){};
                    ~CStack(void){};
   //--- Capacidade mбxima da pilha
   static int        Capacity();
private:
   int               m_length;     // O nъmero de elementos na pilha
   static const int  s_max_length; // Capacidade mбxima da pilha
  };
//+------------------------------------------------------------------+
//| Retorna o nъmero mбximo de elementos armazenados na pilha        |
//+------------------------------------------------------------------+
int CStack::Capacity(void)
  {
   return(s_max_length);
  }
//--- Inicializaзгo da constante estбtica da classe CStack
const int CStack::s_max_length=1000;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- declare CStack type variable
   CStack stack;
//--- call the object's static method
   Print("CStack.s_max_length=",stack.Capacity());
//--- it can also be called the following way, as the method is static and does not require the presence of the object 
   Print("CStack.s_max_length=",CStack::Capacity());
  }

Um método com o modificador const é chamado de constante e não pode alterar membros implícitos de sua classe. A declaração de funções constantes de uma classe e parâmetros constantes é chamado de controle const-correção. Através deste controle pode-se assegurar que o compilador garantirá a consistência de valores de objetos e retornará um erro durante a compilação se existir algo errado.

O modificador const é colocado após a lista de argumentos dentro de uma declaração de classe. A definição do lado de fora de uma classe deve também incluir o modificador const:

//+------------------------------------------------------------------+
//| Class "Retângulo"                                                |
//+------------------------------------------------------------------+
class CRectangle
  {
private:
   double            m_width;      // Largura 
   double            m_height;     // Altura
public:
   //--- Construtor e destrutor
                     CRectangle(void):m_width(0),m_height(0){};
                     CRectangle(const double w,const double h):m_width(w),m_height(h){};
                    ~CRectangle(void){};
   //--- Calculando a área
   double            Square(voidconst;
   static double     Square(const double w,const double h);// { return(w*h); }
  };
//+------------------------------------------------------------------+
//| Retorna a área do objeto "Retângulo"                             |
//+------------------------------------------------------------------+
double CRectangle::Square(voidconst
  {
   return(Square(m_width,m_height));
  }
//+------------------------------------------------------------------+
//| Retorna o produto de duas variáveis                              |
//+------------------------------------------------------------------+
static double CRectangle::Square(const double w,const double h)
  {
   return(w*h);
  }
//+------------------------------------------------------------------+
//| Programa Script da função start (iniciar)                        |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Criar um retângulo reto com os lados iguais a 5 e 6
   CRectangle rect(5,6);
//--- Procurar a área do retângulo usando um método constante
   PrintFormat("rect.Square()=%.2f",rect.Square());
//--- Procurar o produto de números usando o método estático da classe CRectangle
   PrintFormat("CRectangle::Square(2.0,1.5)=%f",CRectangle::Square(2.0,1.5));
  }

Um argumento adicional a favor do uso do controle de constância é o fato de que neste caso, o compilador gera uma otimização especial, por exemplo, coloca um objeto constante na memória de somente-leitura.

Uma função estática não pode ser determinada com o modificador const, porque este modificar garante a constância dos membros de instância quando chamar esta função. Mas, como mencionado acima, a função estática não pode acessar membros de classe não estática.

Também Veja

Variáveis Estáticas, Variáveis, Referências. Modificador & e Palavra-chave this