Ответ
В C++ для ограничения числа экземпляров класса обычно используют статический счетчик. Вот надежная реализация:
#include <stdexcept>
class SingletonLike {
static inline int instanceCount = 0; // Счетчик существующих объектов
static constexpr int MAX_INSTANCES = 3; // Жесткий лимит
public:
SingletonLike() {
// Проверяем лимит в конструкторе
if (instanceCount >= MAX_INSTANCES) {
throw std::runtime_error("Cannot create more than " +
std::to_string(MAX_INSTANCES) + " instances");
}
++instanceCount;
std::cout << "Instance created. Total: " << instanceCount << std::endl;
}
// Важно запретить копирование и присваивание, чтобы обойти лимит
SingletonLike(const SingletonLike&) = delete;
SingletonLike& operator=(const SingletonLike&) = delete;
// Разрешаем перемещение (перехватываем владение)
SingletonLike(SingletonLike&& other) noexcept {
// При перемещении счетчик не увеличивается
}
~SingletonLike() {
--instanceCount;
std::cout << "Instance destroyed. Total: " << instanceCount << std::endl;
}
static int getLiveInstanceCount() { return instanceCount; }
};
// Использование
int main() {
try {
SingletonLike a;
SingletonLike b;
SingletonLike c;
SingletonLike d; // Выбросит исключение
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
}
Альтернативный подход — Singleton (один экземпляр):
class Singleton {
Singleton() = default; // Приватный конструктор
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton& getInstance() {
static Singleton instance; // Создается один раз при первом вызове
return instance;
}
};
Важные моменты:
- Счетчик должен быть статическим — он принадлежит классу, а не объекту.
- Проверка и инкремент — в конструкторе, декремент — в деструкторе.
- Необходимо запретить копирование, иначе можно обойти лимит через
SingletonLike b = a;. - Использование
inlineдля статической переменной (C++17) избавляет от необходимости отдельного определения в .cpp файле.