Потрея типа исключения
От: ML380 Земля  
Дата: 25.08.14 07:57
Оценка: :)
есть код:


try
{
  foo();
}
catch (const std::exception& e)
{
  bar();
  throw e;
}


Будет ли в данном случае потерян тип исключения при последующей ловле?
Есть ли отличия данноного кода от просто "throw"?

Предполагая, что множественного наследования бросаемого объекта нет.
Отредактировано 25.08.2014 7:58 ML380 . Предыдущая версия .
Re: Потрея типа исключения
От: uzhas Ниоткуда  
Дата: 25.08.14 08:12
Оценка: 7 (3)
Здравствуйте, ML380, Вы писали:

ML>Будет ли в данном случае потерян тип исключения при последующей ловле?

будет потерян

ML>Есть ли отличия данноного кода от просто "throw"?

отличия есть. при throw; идет выбрасывание исходного объекта; при throw e; происходит срезка изначального объекта до std::exception

с какой целью интересуетесь?
Re: Потрея типа исключения
От: Кодт Россия  
Дата: 25.08.14 08:17
Оценка: 22 (4)
Здравствуйте, ML380, Вы писали:

ML>Будет ли в данном случае потерян тип исключения при последующей ловле?


Будет, потому что throw кидает значение. Произойдёт банальное копирование со срезкой.

ML>Есть ли отличия данноного кода от просто "throw"?


Собственно, вот они и есть. "просто throw" продолжает работать со старым экземпляром, что позволяет делать, например, такой диспетчер исключений.
void detailed_panic()
{
  try { throw; } // запускаем сопоставление типа
  catch(Foo const& e) { ..... }
  catch(Bar const& e) { ..... }
  .....
  // если дефолтная ветка catch(...) ничего содержательного не делает, можно её не писать
  // из любой ветки можно пробросить исключение выше-дальше с помощью throw;
  // или бросить новое ислючение throw Xyz(......);
}

void alfa(.....)
{
  try { ..... } // делаем что-то полезное
  catch(...) { detailed_panic(); }
}
void beta(.....)
{
  try { ..... }
  catch(...) { detailed_panic(); } // повторно используем код обработки
}

В противном случае пришлось бы вывернуть код наизнанку, прибегнув к функциям (или макросам) высшего порядка
template<class Fun> void run_and_catch(Fun&& fun)
{
  try { fun(); }
  catch(Foo const& e) { ..... }
  catch(Bar const& e) { ..... }
  .....
}

void alfa(.....)
{
  run_and_catch( [&]() { ..... } );
}
// или, по старому стилю,
void beta_impl(.....) { ..... }
void beta()
{
  run_and_catch( boost::bind(beta_impl, .....) );
}

// или на макросах ( узнаёте старый злобрый MFC? )

#define BEGIN_RUN_AND_CATCH() try {
#define END_RUN_AND_CATCH()   } CATCH_FOO() CATCH_BAR() CATCH_OTHERWISE()
#define CATCH_FOO() catch(Foo const& e) { ..... }
// и т.д.

void alfa(.....)
{
  BEGIN_RUN_AND_CATCH()
  .....
  END_RUN_AND_CATCH()
}
void beta(.....)
{
  BEGIN_RUN_AND_CATCH()
  .....
  END_RUN_AND_CATCH()
}
Перекуём баги на фичи!
Отредактировано 25.08.2014 8:20 Кодт . Предыдущая версия .
Re[2]: Потрея типа исключения
От: ML380 Земля  
Дата: 25.08.14 09:15
Оценка:
Здравствуйте, uzhas, Вы писали:

Спасибо.

U>с какой целью интересуетесь?


Нашел в коде проекта, были сомнения.
Re[2]: Потрея типа исключения
От: sizeof_void Россия  
Дата: 25.08.14 16:33
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, ML380, Вы писали:


ML>>Будет ли в данном случае потерян тип исключения при последующей ловле?

U>будет потерян

ML>>Есть ли отличия данноного кода от просто "throw"?

U>отличия есть. при throw; идет выбрасывание исходного объекта; при throw e; происходит срезка изначального объекта до std::exception

U>с какой целью интересуетесь?



Странно, надо проверить конечно.
Но мне кажется, что "(const std::exception& e)" — это ссылочная переменная на исходный объект, а значит, её проброс далее не должен делать срезку.
"May the Force be with us all!" (c)
Re[3]: Потрея типа исключения
От: uzhas Ниоткуда  
Дата: 25.08.14 16:47
Оценка: 7 (1) +1
Здравствуйте, sizeof_void, Вы писали:

_>Но мне кажется, что "(const std::exception& e)" — это ссылочная переменная на исходный объект, а значит, её проброс далее не должен делать срезку.


рассуждаете логично, но плюсы — дело тонкое
throw e; кидает объект по значению, а не по ссылке. при копировании создается срезанный объект

http://stackoverflow.com/questions/2274661/throwing-non-const-temporaries-by-reference
Re[4]: Потрея типа исключения
От: sizeof_void Россия  
Дата: 25.08.14 17:14
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, sizeof_void, Вы писали:


_>>Но мне кажется, что "(const std::exception& e)" — это ссылочная переменная на исходный объект, а значит, её проброс далее не должен делать срезку.


U>рассуждаете логично, но плюсы — дело тонкое

U>throw e; кидает объект по значению, а не по ссылке. при копировании создается срезанный объект

U>http://stackoverflow.com/questions/2274661/throwing-non-const-temporaries-by-reference


Да, я проверил. Действительно, так и происходит.
"May the Force be with us all!" (c)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.