Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Исключение нужно бросить в конструкторе. Как поступаете в таких случаях? 
V
    Опции темы
 
Исключения, бросаемые в конструкторе, - что вы с ними делаете?
ничего не делаю: надо бросить - бросаю [ 24 ]  [48.98%]
стараюсь не бросать исключений в конструкторах, но иногда приходится [ 11 ]  [22.45%]
никогда не бросаю исключений в конструкторах [ 8 ]  [16.33%]
бросаю исключения только в конструкторах [ 1 ]  [2.04%]
не выбрасываю исключение, а делаю что-то другое (написать, что именно). [ 5 ]  [10.20%]
Всего проголосовавших: 49
В этом опросе возможен один вариант ответа
Гости не могут голосовать 
JackYF
  Дата 9.1.2008, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Собственно, сабж. По текущей архитектуре кода исключение должно броситься в конструкторе объекта, если инициализация прошла неуспешно. Код ошибки вернуть не могу - конструктор всё-таки smile.

А что вы делаете в таких случаях?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
marcusmae
Дата 9.1.2008, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 5
Всего: 39



JackYF, замечательный опрос!

Я ответил, что стараюсь не бросать исключений в конструкторах, но иногда приходится. А вообще, думаю, что у меня на этот счёт пробел в теоретических познаниях : ума не приложу, что ж ещё делать, если конструктору скормили, скажем, недопустимое значение аргумента. Хуже того, это какой-нить десятый сверху базовый конструктор, который вызывается по ":" из конструктора наследуемого класса... Интересно, какие будут идеи по поводу последнего варианта ответа.

Это сообщение отредактировал(а) marcusmae - 9.1.2008, 19:37


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
archimed7592
Дата 9.1.2008, 19:44 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



Ответил 1-й вариант(надо бросить - бросаю), но есть у меня маленькое уточнение smile.
"Надо" - понятие растяжимое. Скажем так, если можно без крови перепроектировать несколько классов, чтобы бросать исключение не пришлось, то я именно так и сделаю. Другими словами - не всегда "надо", даже если кажется, что "просто необходимо" smile.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
nickless
Дата 9.1.2008, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

Репутация: 19
Всего: 181



ИМХО если пользуешься исключениями, так пользуйся, а как раз в конструкторе удобно, не надо ничего изобретать.


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
Earnest
Дата 9.1.2008, 20:24 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Я выбрала первый вариант... Строго говоря, что в конструкторе исключения бросать, что в других функция - лишь бы не в деструкторе.
Однако на практике я делаю все же немного по-другому, особенно если речь идет о глобально используемых классах-объектах. Такой конструктор (который может привести к исключению) я делаю приватным и заворачиваю в фабричную функцию (обычно статик этого же класса). И она возвращает уже указатель или 0, обрабатывая исключения или просто проверяя условия внутри себя. 
Решение зависит от контекста - ведь исключения исключениям рознь. Неправильный параметр - если только его не пользователь ввел (или он откуда-то извне появился) - это должно быть выковырено на этапе отладки - здесь лучше исключения и\или ASSERT's.
А вот несуществующий файл или отсутствие ресурса или еще что-то в этом роде - другое дело. При этом, если обработка неудачного создания всегда одинакова, фабричная функция имеет преимущества - пишешь обработку один раз, а потом только if 0 return - несколько короче, чем try\catch, да еще если неоднократно...



--------------------
...
PM   Вверх
JackYF
Дата 9.1.2008, 20:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(Earnest @  9.1.2008,  19:24 Найти цитируемый пост)
Строго говоря, что в конструкторе исключения бросать, что в других функция - лишь бы не в деструкторе.

Разве? ЕМНИП, контейнеры STL по этому поводу не гарантируют уже не помню что, если в конструкторе может выброситься исключение.
Скажем, если я создаю вектор из 10 элементов, и 5-й конструктор выбросил исключение - то в каком состоянии останется контейнер?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
archimed7592
Дата 9.1.2008, 20:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



Цитата(JackYF @  9.1.2008,  20:40 Найти цитируемый пост)
то в каком состоянии останется контейнер? 

Его конструктор выкинет исключение(как new T[]).


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
JackYF
Дата 9.1.2008, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(archimed7592 @  9.1.2008,  19:44 Найти цитируемый пост)
Его конструктор выкинет исключение(как new T[]). 

отлично, а кто будет освобождать память из-под 4 элементов, конструкторы которых уже вызвались?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
archimed7592
Дата 9.1.2008, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



Цитата(JackYF @  9.1.2008,  20:53 Найти цитируемый пост)
отлично, а кто будет освобождать память из-под 4 элементов, конструкторы которых уже вызвались? 

Ну, во-первых, память выделяется под всё сразу. А, во-вторых, как и в случае new T[], вызовутся деструкторы уже сконструированных элементов в порядке, обратном конструированию, потом освободится память(та что под всё сразу) и, наконец, исключение будет переброшено.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
bsa
Дата 9.1.2008, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(archimed7592 @ 9.1.2008,  21:45)
Ну, во-первых, память выделяется под всё сразу. А, во-вторых, как и в случае new T[], вызовутся деструкторы уже сконструированных элементов в порядке, обратном конструированию, потом освободится память(та что под всё сразу) и, наконец, исключение будет переброшено.

Код
#include <iostream>
#include <exception>
#include <vector>
#include <string>

struct Error : public std::exception
{
        Error(const std::string &text) throw() : m_text(text) {}
        ~Error() throw(){}
        const char* what() const throw() {
                return m_text.c_str();
        }
private:
        std::string m_text;
};

class Test
{
        static int counter;
        int cnt;
public:
        Test() {
                cnt = counter;
                if (--counter)
                        throw Error("Error");
        }
        ~Test() {
                std::cout << "Cnt=" << cnt << " destroyed" << std::endl;
                ++counter;
        }
};

int Test::counter = 5;

int main()
{
        try {
                std::vector<Test> test(10);
        } catch(std::exception &e) {
                std::cerr << "Exception: " << e.what() << std::endl;
        }
        return 0;
}
Вывод
Код
$ ./a.out 
Exception: Error
gcc версия 4.1.2 (Gentoo 4.1.2)
Я что-то делаю нетак?
PM   Вверх
JackYF
Дата 9.1.2008, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(archimed7592 @  9.1.2008,  20:45 Найти цитируемый пост)
уже сконструированных элементов в порядке, обратном конструированию

в том-то и дело, что могут не вызваться - конструктор не отработал - мы не имеем право вызывать деструктор.

Добавлено через 57 секунд
о, bsa, отлично, уже живой пример есть smile


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
archimed7592
Дата 9.1.2008, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



Цитата(bsa @  9.1.2008,  21:52 Найти цитируемый пост)
Я что-то делаю нетак? 

Угу. Замени if (--counter) на if (!--counter).

Добавлено через 1 минуту и 12 секунд
Цитата(JackYF @  9.1.2008,  22:26 Найти цитируемый пост)
в том-то и дело, что могут не вызваться - конструктор не отработал - мы не имеем право вызывать деструктор.

Так, давай, с чувством, с толком, с расстановкой - чей конструктор не отработал, чей деструктор не имеем право вызвать и т.д. smile.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
nickless
Дата 9.1.2008, 22:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

Репутация: 19
Всего: 181



Вот Standard-Library Exception Safety от Страуструпа [pdf, 200kB] как дополнение к его же FAQу


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
bsa
Дата 9.1.2008, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(archimed7592 @ 9.1.2008,  22:28)
Цитата(bsa @  9.1.2008,  21:52 Найти цитируемый пост)
Я что-то делаю нетак? 

Угу. Замени if (--counter) на if (!--counter).

 smile 
Там не только это нужно было исправить.
Код
#include <iostream>
#include <exception>
#include <vector>
#include <string>

struct Error : public std::exception
{
        Error(const std::string &text) throw() : m_text(text) {}
        ~Error() throw(){}
        const char* what() const throw() {
                return m_text.c_str();
        }
private:
        std::string m_text;
};

class Test
{
        static int counter;
        int cnt;
public:
        Test() {
                cnt = counter--;
                if (!counter)
                        throw Error("Error");
                std::cout << "Cnt=" << cnt << " created" << std::endl;
        }
        Test(const Test&) {
                cnt = counter--;
                if (!counter)
                        throw Error("Error");
                std::cout << "Cnt=" << cnt << " created" << std::endl;
        }
        ~Test() {
                std::cout << "Cnt=" << cnt << " destroyed" << std::endl;
                ++counter;
        }
};

int Test::counter = 5;

int main()
{
        try {
                std::vector<Test> test(10);
        } catch(std::exception &e) {
                std::cerr << "Exception: " << e.what() << std::endl;
        }
        return 0;
}
Зато вывод стал таким:
Код
$ ./a.out 
Cnt=5 created
Cnt=4 created
Cnt=3 created
Cnt=2 created
Cnt=4 destroyed
Cnt=3 destroyed
Cnt=2 destroyed
Cnt=5 destroyed
Exception: Error

PM   Вверх
JackYF
Дата 9.1.2008, 23:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 18
Всего: 162



Цитата(archimed7592 @  9.1.2008,  21:28 Найти цитируемый пост)
чей деструктор не имеем право вызвать

итак, пример.
пускай есть класс с двумя динамическими полями. Пускай в конструкторе под них выделяется память. Что будет, если я выброшу исключение после того, как память под первое поле уже выделил, а под второе ещё нет?
1) деструктор вызовется. При попытке освободить память из-под второго поля (там мусор, так как конструктор ничего не успел с ним сделать) - сегфолт.
2) деструктор не вызовется. Память, выделенная под первое поле, останется витать в воздухе.

Ещё варианты?


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0669 ]   [ Использовано запросов: 24 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.