есть код:
try
{
foo();
}
catch (const std::exception& e)
{
bar();
throw e;
}
Будет ли в данном случае потерян тип исключения при последующей ловле?
Есть ли отличия данноного кода от просто "throw"?
Предполагая, что множественного наследования бросаемого объекта нет.
Здравствуйте, ML380, Вы писали:
ML>Будет ли в данном случае потерян тип исключения при последующей ловле?
будет потерян
ML>Есть ли отличия данноного кода от просто "throw"?
отличия есть. при throw; идет выбрасывание
исходного объекта; при throw e; происходит срезка изначального объекта до std::exception
с какой целью интересуетесь?
Здравствуйте, 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()
}
Здравствуйте, uzhas, Вы писали:
Спасибо.
U>с какой целью интересуетесь?
Нашел в коде проекта, были сомнения.
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, ML380, Вы писали:
ML>>Будет ли в данном случае потерян тип исключения при последующей ловле?
U>будет потерян
ML>>Есть ли отличия данноного кода от просто "throw"?
U>отличия есть. при throw; идет выбрасывание исходного объекта; при throw e; происходит срезка изначального объекта до std::exception
U>с какой целью интересуетесь?
Странно, надо проверить конечно.
Но мне кажется, что "(const std::exception& e)" — это ссылочная переменная на исходный объект, а значит, её проброс далее не должен делать срезку.
Здравствуйте, sizeof_void, Вы писали:
_>Но мне кажется, что "(const std::exception& e)" — это ссылочная переменная на исходный объект, а значит, её проброс далее не должен делать срезку.
рассуждаете логично, но плюсы — дело тонкое
throw e; кидает объект по значению, а не по ссылке. при копировании создается срезанный объект
http://stackoverflow.com/questions/2274661/throwing-non-const-temporaries-by-reference
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, sizeof_void, Вы писали:
_>>Но мне кажется, что "(const std::exception& e)" — это ссылочная переменная на исходный объект, а значит, её проброс далее не должен делать срезку.
U>рассуждаете логично, но плюсы — дело тонкое
U>throw e; кидает объект по значению, а не по ссылке. при копировании создается срезанный объект
U>http://stackoverflow.com/questions/2274661/throwing-non-const-temporaries-by-reference
Да, я проверил. Действительно, так и происходит.