Вызов статического метода перед остановкой программы
Задача состоит в том, чтобы вызвать определенный статический метод перед остановкой программы из-за неизвестной ошибки. С моими знаниями, я предполагаю, что это невозможно. Что я имею ввиду ?
Предположим, что у нас есть класс A:
class A
{
public:
A() { std::cout << " A()" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
};
При инициализации данного класса где бы ни было, обязательно, при выходе из скоупа, или других сценариев, будет вызван деструктор этого класса (за это мы и любим С++). Например:
int main(int argc, char *argv[])
{
A a;
}
// Console output
A()
~A()
Тут все понятно. А вот при объявление статических объектов все немгого по другому:
// ...
static A a;
// ...
Объекты со статическим временем жизни будут уничтожены при завершении работы приложения. С этим так же все понятно. И тут появляется проблема. У меня есть класс, который имеет лишь статические функции. Понятно, что у класса удалены все конструкторы, деструкторы и операторы копирования и перемещения. Назовем этот класс SessionManager:
PS Этот класс приводится только в качестве примера
class SessionManager
{
public:
SessionManager() = delete;
SessionManager &operator=(const SessionManager &) = delete;
SessionManager &operator=(SessionManager &&) = delete;
SessionManager(const SessionManager &) = delete;
SessionManager(SessionManager &&) = delete;
~SessionManager() = delete;
static void stop();
static void start();
static void method_1();
static void method_2();
static void method_3();
static void method_n();
private:
static void worker();
private:
static int arg_1;
static int arg_2;
static int arg_3;
static int arg_n;
static std::thread worker_thread;
};
Метод start запускает 1 поток, в котором и будет производиться главная логика класса. Обязательно до остановки программы, метод stop должен быть вызван! Если этого не сделать, критически важная информация будет потеряна. Но, что будет, если пользователь забудет вызвать данный метод - потеря информации... Как можно решить эту проблему ?
Мысли вслух
Первое, что приходит мне в голову - это переписать класс, а именно сделать его нестатичным, а в деструкторе вызывать метод stop на всякий случай. Но этот класс должен быть инициализирован только 1 раз, что наводит на мысль о синглтонном паттерне (что, честно говоря, не радует).
Ответы (1 шт):
Способ первый - создайте маленький объект, основная задача которого только в деструкторе позвать нужную функцию.
сlass Late
{
public:
~Late() { SessionManager::stop(); }
};
и теперь в main просто пишем
int main()
{
//..
Late l;
//..
}
И все. Можно для этой же цели использовать std::unique_ptr с пользовательским деструктором. Но тут на любителя. Главное, вставить создание этой переменной в нужном месте в начале (можно и в самом начале, а можно даже как глобальную переменную объявить, тут нужно смотреть как красивее).
Второй способ. Есть такая функция - atexit которой просто нужно передать функцию, которую нужно выполнить по завершению программы. Плюсы этого способа, что вызывать эту функцию можно с любого места кода и можно регистрировать много таких функций (они все отработают).
// там где понятно, что нужно вызвать стоп
const int result = std::atexit(SessionManager::stop);
if (result != 0) {
std::cerr << "Registration failed\n";
// обработаем ошибку
}
я бы этот код в start добавил бы