Исключение перехватывается в блоке try конструктора и обрабатывается, но все равно перебрасывается во второй раз - PullRequest
4 голосов
/ 24 апреля 2020

Я пытаюсь лучше понять механизм throw-catch при работе с наследованием.

Проблема, которую я пытаюсь решить, - это случай того, что произойдет, если при создании производного класса базовый класс, который Конструкция сначала выдает исключение.

#include <stdexcept>
#include <iostream>

class Base
{
    public:
    Base()
    {
        throw  std::runtime_error("test");
    }
};


class Derived : public Base
{
    public:
    Derived() try : Base()
    {

    }
    catch (std::runtime_error& e)
    {
        std::cout <<  "Base throws an exception : " << e.what() << std::endl;
    }    
};


int main ()
{
   Derived temp;
   return (0);
}

После запуска моего скомпилированного кода (g ++ std = 11) я получаю следующее сообщение:

База выдает исключение: test

завершить вызов после выброса экземпляра 'std :: runtime_error'

what (): test

Прервано (ядро сброшено

Мое исключение, выданное Base, перехватывается try-catch конструктора Derived, но по какой-то причине выброшенное исключение на этом не останавливается, почему и как это решить ?

И независимо от того, открыт ли я для предложений, есть ли лучший способ обработки исключения, которое может быть выдано базовым классом при создании производного.

Ответы [ 2 ]

3 голосов
/ 24 апреля 2020

Фундаментальный базовый принцип C ++ заключается в том, что объект полностью создается только после возврата конструктора объекта. Когда выполнение входит в конструктор класса, сам класс создается , а не . Только его члены класса (и любые базовые классы тоже). Только когда возвращается конструктор, только затем объект полностью построен, и у вас есть полностью готовый объект, с которым можно поиграть.

Следовательно, выдается исключение в конструктор означает, что объект был , а не . Полная остановка. Конец истории. Это все что она написала. Нет исключений из этого правила (каламбур).

Теперь, что это значит, когда вы ловите исключение, которое выдается из конструктора базового класса? Ну, вы можете это сделать, но это не меняет того факта, что возникло исключение, а базовый класс не был создан. Это означает, что производный класс не может быть создан . Нельзя ожидать, что выполнение достигнет конца обработчика исключений, а затем вернется к родителю, как если бы класс был полностью создан без ошибок.

Этого не произойдет. Вы не можете каким-то образом получить базовый класс, который не создается, а производный класс создается. C ++ не работает таким образом.

Когда вы перехватываете исключение из базового класса, у вас есть только две опции:

1) Ваш обработчик исключений может перебрасывать свое собственное исключение после того, как он делает что угодно он хочет это сделать.

2) В противном случае C ++ перезапустит исключение для вас, если обработчик исключений вернется, не выдав свое собственное исключение.

1 голос
/ 24 апреля 2020

Да, это правильное поведение. У вас есть блок try / catch, который фиксирует исключения из базового класса и списка инициализаторов. Согласно стандарту это исключение автоматически перебрасывается из блока catch. То же самое верно, если вы захватили исключение в деструкторе, делающем попытку / поймать тело деструктора.

...