Menu
Coddy logo textTech

Métodos e Variáveis Estáticos

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 31 de 104.

Você aprendeu que membros estáticos são compartilhados entre todos os objetos. Agora vamos explorar como definir e usar adequadamente métodos estáticos junto com variáveis estáticas.

Variáveis estáticas declaradas dentro de uma classe devem ser definidas fora da classe, geralmente em um arquivo de origem. Isso ocorre porque membros estáticos precisam de exatamente um local de armazenamento compartilhado por todos os objetos:

class Counter {
    static int count;    // Apenas declaração
    
public:
    Counter() { count++; }
    ~Counter() { count--; }
    
    static int getCount() {    // Método estático
        return count;
    }
};

// Definição - necessária fora da classe
int Counter::count = 0;

Um método estático pertence à classe, não a nenhum objeto. Isso tem uma consequência importante: métodos estáticos não podem acessar membros de instância ou usar o ponteiro this, porque eles não são chamados em nenhum objeto específico.

class MathUtils {
    static double pi;
    
public:
    static double circleArea(double radius) {
        return pi * radius * radius;    // Pode acessar membros estáticos
    }
};

double MathUtils::pi = 3.14159;

// Chamado sem um objeto
double area = MathUtils::circleArea(5.0);

Métodos estáticos são ideais para funções utilitárias que não precisam do estado do objeto, métodos de fábrica que criam objetos ou para acessar dados estáticos. Como eles não exigem uma instância de objeto, você os chama usando o nome da classe e o operador de resolução de escopo: ClassName::methodName().

challenge icon

Desafio

Fácil

Vamos construir um sistema gerador de IDs únicos que demonstra como métodos e variáveis estáticas trabalham juntos para fornecer funcionalidade em nível de classe sem a necessidade de instâncias de objetos.

Você criará dois arquivos para organizar seu código:

  • IDGenerator.h: Defina uma classe IDGenerator que gera IDs únicos sequenciais. Sua classe deve ter:
    • Um membro estático privado nextId que rastreia o próximo ID a ser atribuído (começa em 1000)
    • Um membro estático privado prefix (string) que armazena um prefixo personalizável para todos os IDs
    • Um método estático setPrefix(const std::string& p) que altera o prefixo
    • Um método estático getNextId() que retorna uma string combinando o prefixo e o número do ID atual, e então incrementa nextId para a próxima chamada
    • Um método estático peekNextId() que retorna qual seria o próximo ID sem incrementar o contador
    • Um método estático getGeneratedCount() que retorna quantos IDs foram gerados (dica: calcule a partir do valor inicial e do nextId atual)
    • Um método estático reset() que redefine nextId de volta para 1000

    Lembre-se de definir seus membros estáticos fora da classe após a definição da classe. Inicialize prefix como "ID-".

  • main.cpp: Demonstre a chamada de métodos estáticos usando o nome da classe sem criar nenhum objeto. Leia um prefixo personalizado da entrada e, em seguida:

    • Imprima "Peek: <peeked_id>" usando peekNextId()
    • Gere três IDs usando getNextId() e imprima cada um como "Generated: <id>"
    • Imprima "Count: <count>" mostrando quantos IDs foram gerados
    • Altere o prefixo usando o valor de entrada com setPrefix()
    • Gere mais dois IDs e imprima cada um como "Generated: <id>"
    • Imprima "Count: <count>" novamente
    • Chame reset()
    • Imprima "After reset - Peek: <peeked_id>"
    • Imprima "After reset - Count: <count>"

Observe que você nunca cria um objeto IDGenerator — todos os métodos são chamados diretamente na classe usando IDGenerator::methodName(). Esta é a característica fundamental dos métodos estáticos: eles pertencem à própria classe, não a nenhuma instância específica.

Inclua <string> e <iostream> em seu arquivo de cabeçalho e não se esqueça dos "header guards".

Folha de consulta

Variáveis estáticas declaradas dentro de uma classe devem ser definidas fora da classe. Membros estáticos precisam de exatamente um local de armazenamento compartilhado por todos os objetos:

class Counter {
    static int count;    // Apenas declaração
    
public:
    Counter() { count++; }
    
    static int getCount() {
        return count;
    }
};

// Definição - necessária fora da classe
int Counter::count = 0;

Um método estático pertence à classe, não a qualquer objeto. Métodos estáticos não podem acessar membros de instância ou usar o ponteiro this porque não são chamados em nenhum objeto específico:

class MathUtils {
    static double pi;
    
public:
    static double circleArea(double radius) {
        return pi * radius * radius;    // Pode acessar membros estáticos
    }
};

double MathUtils::pi = 3.14159;

// Chamado sem um objeto usando o nome da classe
double area = MathUtils::circleArea(5.0);

Métodos estáticos são chamados usando o nome da classe e o operador de resolução de escopo: ClassName::methodName(). Eles são ideais para funções utilitárias que não precisam do estado do objeto, métodos de fábrica ou acesso a dados estáticos.

Experimente você mesmo

#include <iostream>
#include <string>
#include "IDGenerator.h"

using namespace std;

int main() {
    // Lê o prefixo personalizado da entrada
    string customPrefix;
    cin >> customPrefix;
    
    // TODO: Imprima "Peek: <peeked_id>" usando peekNextId()
    
    // TODO: Gere três IDs usando getNextId() e imprima cada um como "Generated: <id>"
    
    // TODO: Imprima "Count: <count>" mostrando quantos IDs foram gerados
    
    // TODO: Altere o prefixo usando o valor de entrada com setPrefix()
    
    // TODO: Gere mais dois IDs e imprima cada um como "Generated: <id>"
    
    // TODO: Imprima "Count: <count>" novamente
    
    // TODO: Chame reset()
    
    // TODO: Imprima "After reset - Peek: <peeked_id>"
    
    // TODO: Imprima "After reset - Count: <count>"
    
    return 0;
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos