Sobes.tech
Middle+

Jak ograniczyć liczbę instancji klasy w C++?

sobes.tech AI

Odpowiedź od AI

Istnieje kilka metod, główne to:

  1. Użycie statycznej zmiennej licznika:

    • Utwórz statyczną zmienną typu int do śledzenia liczby utworzonych instancji.
    • Zwiększ licznik w konstruktorze.
    • Zmniejsz licznik w destruktorze.
    • W konstruktorze sprawdź wartość licznika i, jeśli przekracza limit, wyrzuć wyjątek lub podejmij inne działania.
    • Uczyń konstruktor prywatnym lub chronionym, a tworzenie instancji realizuj przez statyczną funkcję fabryczną, która wykonuje sprawdzenie.
    • Zabroń kopiowania i przenoszenia.
    #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("Osiągnięto maksymalną liczbę instancji.");
            }
            instance_count++;
            std::cout << "Utworzono instancję. Razem: " << instance_count << std::endl;
        }
    
        // Zabroń kopiowania i przenoszenia
        LimitedInstances(const LimitedInstances&) = delete;
        LimitedInstances& operator=(const LimitedInstances&) = delete;
        LimitedInstances(LimitedInstances&&) = delete;
        LimitedInstances& operator=(LimitedInstances&&) = delete;
    
    public:
        ~LimitedInstances() {
            instance_count--;
            std::cout << "Zniszczono instancję. Razem: " << instance_count << std::endl;
        }
    
        static LimitedInstances* create_instance() {
            return new LimitedInstances();
        }
    };
    
    int LimitedInstances::instance_count = 0;
    
  2. Użycie wzorca Singleton z modyfikacją:

    • Zazwyczaj Singleton gwarantuje jedną instancję. Aby ograniczyć liczbę instancji, można go zmodyfikować, zarządzając dostępem do tworzenia przez funkcję statyczną i śledząc utworzone obiekty w prywatnym statycznym kontenerze (np. std::vector lub 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 utworzony." << std::endl;
        }
    
        // Zabroń kopiowania i przenoszenia
        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("Osiągnięto maksymalną liczbę NLimitedInstances.");
            }
            NLimitedInstances* new_instance = new NLimitedInstances();
            instances.push_back(new_instance);
            return new_instance;
        }
    
        static void destroy_instance(NLimitedInstances* instance) {
            // Szukaj i usuwaj instancję z wektora
            for (auto it = instances.begin(); it != instances.end(); ++it) {
                if (*it == instance) {
                    delete *it;
                    instances.erase(it);
                    std::cout << "NLimitedInstances zniszczony." << std::endl;
                    return;
                }
            }
        }
    
        ~NLimitedInstances() = default; // lub dodaj logikę czyszczenia
    };
    
    std::vector<NLimitedInstances*> NLimitedInstances::instances;
    

Oba podejścia wymagają ostrożnego zarządzania zasobami, szczególnie przy użyciu new. Wzorzec Singleton z modyfikacją może być bardziej skomplikowany w implementacji destrukcji obiektów, szczególnie jeśli ich cykl życia nie pokrywa się z końcem programu.

Wybór metody zależy od konkretnych wymagań i złożoności systemu. Podejście z licznikiem statycznym jest ogólnie prostsze do zrozumienia i wdrożenia.