Padrões de Design para Classes com Restrições Específicas em C++

1. Classes Não Copiáveis

Em diversos cenários de desenvolvimento, como no gerenciamento de recursos exclusivos (file descriptors, sockets), é necessário garantir que um objeto não seja duplicado. Para impedir a cópia, devemos desativar o construtor de cópia e o operador de atribuição.

class BloqueioDeCopia {
public:
    BloqueioDeCopia() = default;
    
    // Desativando explicitamente a cópia e a atribuição (C++11)
    BloqueioDeCopia(const BloqueioDeCopia&) = delete;
    BloqueioDeCopia& operator=(const BloqueioDeCopia&) = delete;
};

2. Classes com Alocação Exclusiva no Heap

Para forçar que um objeto seja criado apenas na memória dinâmica (heap), o construtor deve ser tornado privado. O acesso à criação do objeto é então disponibilizado através de um método estático que retorna um ponteiro.

class ApenasHeap {
public:
    static ApenasHeap* CriarInstancia() {
        return new ApenasHeap();
    }

    // Método para destruir o objeto, já que o destrutor pode ser privado
    void Destruir() {
        delete this;
    }

private:
    ApenasHeap() {}
    // Impedir cópia para evitar instâncias na stack via cópia
    ApenasHeap(const ApenasHeap&) = delete;
    ApenasHeap& operator=(const ApenasHeap&) = delete;
};

3. Classes com Alocação Exclusiva na Stack

Para restringir a criação de objetos apenas à pilha (stack), impedindo o uso do operador new, podemos sobrecarregar os operadores de alocação de memória como privados ou simplesmente deletá-los.

class ApenasStack {
public:
    ApenasStack() {}

    // Deletar os operadores new e delete impede alocação no heap
    void* operator new(size_t size) = delete;
    void operator delete(void* ptr) = delete;
};

4. Classes Não Herdáveis (Finais)

No C++ moderno, a forma mais eifciente de impedir que uma classe seja utilizada como base para outras é através da palavra-chave final. Antes do C++11, isso era simulado tornando os construtores privados.

// Abordagem moderna com 'final'
class ClasseTerminal final {
    // Implementação
};

// Tentativa de herança resultará em erro de compilação:
// class Falha : public ClasseTerminal {}; 

5. Implementação do Padrão Singleton

O Singleton garante que uma classe possua apenas uma instância em todo o ciclo de vida da aplicação, fornecendo um ponto global de acesso.

Abordagem Eager (Faminta)

A instância é criada no momento em que o programa é carregado, antes mesmo da execução do main. É inerentemente segura para threads, mas pode impactar o tempo de inicialização.

class SingletonEager {
public:
    static SingletonEager* GetInstance() {
        return &instancia;
    }

private:
    SingletonEager() {}
    SingletonEager(const SingletonEager&) = delete;
    SingletonEager& operator=(const SingletonEager&) = delete;

    static SingletonEager instancia;
};

// Inicialização estática
SingletonEager SingletonEager::instancia;

Abordagem Lazy (Preguiçosa)

A instância é criada apenas quando o método de acesso é invocado pela primeira vez. Para graantir a limpeza correta da memória, pode-se utilizar uma classe interna auxiliar (Garbage Colllector).

class SingletonLazy {
public:
    static SingletonLazy* GetInstance() {
        if (ptr_instancia == nullptr) {
            ptr_instancia = new SingletonLazy();
        }
        return ptr_instancia;
    }

    // Classe interna para desalocação automática
    class Coletor {
    public:
        ~Coletor() {
            if (SingletonLazy::ptr_instancia) {
                delete SingletonLazy::ptr_instancia;
                SingletonLazy::ptr_instancia = nullptr;
            }
        }
    };

private:
    SingletonLazy() {}
    SingletonLazy(const SingletonLazy&) = delete;
    SingletonLazy& operator=(const SingletonLazy&) = delete;

    static SingletonLazy* ptr_instancia;
    static Coletor coletor;
};

// Inicialização de membros estáticos
SingletonLazy* SingletonLazy::ptr_instancia = nullptr;
SingletonLazy::Coletor SingletonLazy::coletor;

Tags: C++ OOP design patterns Memory Management singleton

Publicado em 7-27 14:25