Sobes.tech
Middle+

Como limitar o número de instâncias de uma classe em C++?

sobes.tech IA

Resposta da IA

Existem várias formas, as principais:

  1. Utilização de uma variável estática contador:

    • Criar uma variável estática do tipo int para rastrear o número de instâncias criadas.
    • Incrementar o contador no construtor.
    • Decrementar o contador no destruidor.
    • No construtor, verificar o valor do contador e, se o limite for excedido, lançar uma exceção ou tomar outras ações.
    • Tornar o construtor privado ou protegido, e criar instâncias através de uma função de fábrica estática que realiza a verificação.
    • Proibir a cópia e o movimento.
    #include <iostream>
    #include <stdexcept>
    
    class LimitedInstances {
    private:
        static int instance_count;
        static const int max_instances = 3;
    
        LimitedInstances() {
            if (instance_count >= max_instances) {
                throw std::runtime_error("Número máximo de instâncias atingido.");
            }
            instance_count++;
            std::cout << "Instância criada. Total: " << instance_count << std::endl;
        }
    
        // Proibir cópia e movimento
        LimitedInstances(const LimitedInstances&) = delete;
        LimitedInstances& operator=(const LimitedInstances&) = delete;
        LimitedInstances(LimitedInstances&&) = delete;
        LimitedInstances& operator=(LimitedInstances&&) = delete;
    
    public:
        ~LimitedInstances() {
            instance_count--;
            std::cout << "Instância destruída. Total: " << instance_count << std::endl;
        }
    
        static LimitedInstances* create_instance() {
            return new LimitedInstances();
        }
    };
    
    int LimitedInstances::instance_count = 0;
    
  2. Utilização do padrão Singleton com modificação:

    • Normalmente, Singleton garante uma instância. Para limitar o número de instâncias, pode-se modificá-lo, gerenciando o acesso à criação através de uma função estática e rastreando os objetos criados em um contêiner estático privado (por exemplo, std::vector ou std::list).
    #include <iostream>
    #include <vector>
    #include <stdexcept>
    
    class NLimitedInstances {
    private:
        static std::vector<NLimitedInstances*> instances;
        static const int max_instances = 2;
    
        NLimitedInstances() {
            std::cout << "NLimitedInstances criado." << std::endl;
        }
    
        // Proibir cópia e movimento
        NLimitedInstances(const NLimitedInstances&) = delete;
        NLimitedInstances& operator=(const NLimitedInstances&) = delete;
        NLimitedInstances(NLimitedInstances&&) = delete;
        NLimitedInstances& operator=(NLimitedInstances&&) = delete;
    
    public:
        static NLimitedInstances* get_instance() {
            if (instances.size() >= max_instances) {
                 throw std::runtime_error("Número máximo de NLimitedInstances atingido.");
            }
            NLimitedInstances* new_instance = new NLimitedInstances();
            instances.push_back(new_instance);
            return new_instance;
        }
    
        static void destroy_instance(NLimitedInstances* instance) {
            // Procurar e remover a instância do vetor
            for (auto it = instances.begin(); it != instances.end(); ++it) {
                if (*it == instance) {
                    delete *it;
                    instances.erase(it);
                    std::cout << "NLimitedInstances destruído." << std::endl;
                    return;
                }
            }
        }
    
        ~NLimitedInstances() = default; // ou adicionar lógica de limpeza
    };
    
    std::vector<NLimitedInstances*> NLimitedInstances::instances;
    

Ambas as abordagens requerem uma gestão cuidadosa de recursos, especialmente ao usar new. O padrão Singleton com modificação pode ser mais complexo na implementação da destruição de objetos, especialmente se seu ciclo de vida não coincidir com o encerramento do programa.

A escolha do método depende dos requisitos específicos e da complexidade do sistema. A abordagem com contador estático é geralmente mais simples de entender e implementar.