Домівка > C++ > Виняткові ситуації в конструкторах і деструкторах

Виняткові ситуації в конструкторах і деструкторах

У програмістів на C++ часто виникають запитання про те, чи можна кидати винятки у конструкторах і деструкторах. У цій статті ми розглянемо обидва питання.

Що робити якщо конструктор зазнав невдачі?

Кинути виняток.

Конструктори не мають типу повернення, отже неможливо повернути код помилки. Найкращим варантом сповістити про помилку в конструкторі — кинути виняток. Якщо в вашій програмі заборонено використання виняткових ситуацій, то можна використати варіант переведення об’єкта у зомбі-стан,так щоб він поводився наче мертвий хоча технічно він ще живий.

Ідея зомбі-об’єктів має багато вад. Вам потрібно додати функцію-член для перевірки на ти чи цей об’єкт є зомбі. Кожен раз по створення такого об’єкта необхідно викликати цю функцію для перевірки стану об’єкта.

Звісно, варто віддати перевагу винятковій ситуації, а не зомбі-об’єкту.

Заувага: якщо конструктор кинув виняток, пам’ять пов’язана з об’єктом вивільняється, отже немає витоку пам’яті. Наприклад:

void f()
{
  X x;             // Якщо X::X() кидає виняток, пам'ять під x не буде втрачено
  Y* p = new Y();  // Якщо Y::Y() кидає виняток, пам'ять під *p не буде втрачено
}

У випадку якщо сам конструктор виділяє пам’ять, то необхідно вжити додаткових заходів для її вивільнення.

Кидання винятку з деструктора є небезпечним

Якщо у цей час поширюється інший виняток, то програма перерветься.

#include <iostream>

class Bad
{
    public:
        ~Bad()
        {
            throw 1;
        }
};

int main()
{
    try
    {
        Bad   bad;
    }
    catch(...)
    {
        std::cout << "Надрукувати це" << std::endl;
    }

    try
    {
        Bad   bad;
        throw 2;
    }
    catch(...)
    {
        std::cout << "Ніколи не друкувати це" << std::endl;
    }
}

Це зводиться до:

Все небезпечне, тобто таке, що може кинути виняток, необхідно робити у відкритих методах класу (не обов’язково прямо). Тоді користувач вашого класу може обробити такі надзвичайні ситуації власноруч.

Деструктор потім завершить об’єкт через виклик цих методів (якщо користувач не зробив цього явно), але будь-які винятки перехоплюються і губляться (після спробу виправити ситуацію).

Отже, по суті, ви передаєте відповідальність користувачеві. Якщо користувач може виправити ситуацію, то він сам викличе необхідні функції і обробить помилки. Якщо користувач не турбується про те, як відбудеться знищення об’єкта, то він може залишити цю справу деструктору.

Приклад:

std::fstream

Метод close() потенційно може кинути виняток. Деструктор викликає close() якщо файл відкритий і опікується тим, щоб винятки не поширились за його межі.

Таким чином, якщо користувач файлу бажає виконати особливу обробку у випадку винятку при закритті файлу, то він може викликати цей метод власноруч. Або ж файл закриє деструктор.

Advertisements
Категорії:C++ Позначки:
  1. Коментарів ще немає.
  1. No trackbacks yet.

Залишити відповідь

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out / Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out / Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out / Змінити )

Google+ photo

Ви коментуєте, використовуючи свій обліковий запис Google+. Log Out / Змінити )

З’єднання з %s

%d блогерам подобається це: