Ex.what() изменение вложенного try-catch
У меня есть вложенный код try-catch, как показано ниже:
void A()
{
try
{
//Code like A = string(NULL) that throws an exception
}
catch(std::exception& ex)
{
cout<<"in A : " << ex.what();
throw ex;
}
}
void B()
{
try
{
A();
}
catch(std::exception& ex)
{
cout<<"in B : " << ex.what();
}
}
После этого я получил этот результат:
in A: basic_string::_M_construct null not valid
in B: std::exception
Как вы можете видеть, ex.what()
работает нормально в функции A и скажет мне правильное описание, но в B ex.what()
мне просто говорит std::exception
. Почему это происходит?
Я бросаю что-то другое или неправильное в предложение catch функции A? Как мне вставить вложенное исключение, чтобы я мог получить точное описание исключения в B?
Ответы
Ответ 1
Замените throw ex;
на throw;
.
Выполнение последнего будет повторно выбрасывать исключение ex
по ссылке, чтобы устранить опасности при попытке сделать копию значения: см. Что такое обрезка объектов?
(Обратите внимание, что вам разрешено изменять ex
, даже если вы пишете throw
).
Ответ 2
Вы бросаете копию исключения ex
в A
. Что вызывает разбиение объектов, которое превращает конкретное исключение в std::exception
.
Чтобы восстановить фактическое исключение, которое вы обнаружили полиморфно, используйте оператор throw;
.
Следует помнить, что говорит Скотт Мейерс в своей книге. Вы бросаете по значению и должны ловить по ссылке.
Ответ 3
Вы slicing исходный объект исключения, попробуйте
try {
throw std::runtime_error("Hello world");
}
catch (std::exception& ex)
{
cout << "in A : " << ex.what();
throw; // Rethrows the original exception - no copy or slicing
^^^^^^
}