Подтвердить что ты не робот

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?

4b9b3361

Ответ 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
  ^^^^^^
}