А можно ли бросать исключения из конструктора?

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Так мало ли где этот if валяется. Может за cathc?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

Каким образом ты собираешься передать туда указатель на тот участок памяти где пытались сконструировать объект?
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

А зачем мне указатель? Он ваще то именован.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Absurd
Сообщения: 1228
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

напиши полный код с catch.
2B OR NOT(2B) = FF
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Код: Выделить всё

std::ifsream f;
int x;
try
{
 A a(123);
}
catch (const std::u32string &ErrorMessage)
{
 Log<<ErrorMessage;
}
if ((bool)a)
{
 f.open(a[0]);
 f>>x;
 f.close();
}
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Сионист, а ничего, что а уже не существует в том месте, где ты делаешь if? Ты имеешь хоть базовые понятия об областях видимости? Ну, или на худой конец, не пробовал хотя бы скомпилировать свой код?

По поводу ответа на твой вопрос. Да, из конструкторов можно кидать исключения. Стандартом полностью прописано поведение кода в этом случае.

- Деструкторы будут автоматически вызваны для всех уже инициализированных базовых классов (если исключение полетело из базового конструктора)

- Деструкторы будут автоматически вызваны для всех уже инициализированных базовых классов и уже инициализированных полей текущего класса (если исключение полетело в списке инициализации)

- За все иные утечки ответственен программист (то есть если мы выделяем память под некие поля в теле конструктора, а не в списке инициализации, то можем попасть в ситуацию partial initialization, для избежания которой обязаны ловить исключение внутри тела конструктора, в catch делать "чистку", а затем пробрасывать исключение дальше).

- Объект, для которого было проброшено исключение построенным не считается.

И если уж на то пошло, то этот вопрос отлично гуглится...
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

А для объектов, агрегированных не построенным объектом деструкторы будут вызваны?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Я же достаточно ясно написал об этом, вроде:
Romeo писал(а): - Деструкторы будут автоматически вызваны для всех ... уже инициализированных полей текущего класса (если исключение полетело в списке инициализации)
- За все иные утечки ответственен программист...
Подробнее объяснить? Я не знаю, куда уже подробнее.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

При чём здесь список инициализации?

Код: Выделить всё

A
{
 std::ustring s;
 public:
 A (const int &x)
 {
   s=U"...";
   ...
   throw ...;
 }
};
A a(2);
Будет ли вызван деструктор для a.s, если при создании a было брошено исключение?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Да, будет. Так как s был инициализирован. А список инициализации здесь при том, что этот самый s был инициализирован именно в нём, хоть и неявно. Если исключение полетит при инициализации одного из полей, то деструкторы будут вызваны только для тех полей, которые уже были инициализированы.

Код: Выделить всё

class Composite
{
   Composite()
      a1(),
      a2(),  // <---- exception here
      a3()
   {
      // some code
   }

private:
   Aggreate1 a1;
   Aggreate2 a2;
   Aggreate3 a3;
}
Вот в таком случае:

- Для a1 будет вызван деструктор, так как a1 уже инициализирован на момент генерации исключения.
- Для a2 не будет вызван деструктор, так как объект, из конструктора которого полетело исключение инициализированным не считается.
- Для a3 не будет вызван деструктор, так как инициализация для него ещё не была выполнена.

Так же всё работает и для базовых классов.

А твой случай, когда исключение летит в теле конструктора самый простой и очевидный, так как если мы дошли до тела конструктора, то все поля класса уже инициализированы. Значит для всех них при генерации исключения будет вызван деструктор.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить