Могу ли я иметь вложенные блоки try-catch в C ++? - PullRequest
18 голосов
/ 16 февраля 2009

Могу ли я иметь вложенные блоки try-catch? Например:


void f()
{
    try
    {
        //Some code 
        try
        {
             //Some code 
        }
        catch(ExceptionA a)
        {
            //Some specific exception handling
        }
        //Some code
    }
    catch(...)
    {
        //Some exception handling
    }
}//f

Ответы [ 5 ]

22 голосов
/ 16 февраля 2009

Да, совершенно законно.

Хотя было бы лучше переместить внутренние в другой метод, чтобы он выглядел чище, а ваши методы стали меньше

10 голосов
/ 16 февраля 2009

Как уже говорилось, это возможно, но вы должны увидеть схему «провала» в этом. Если в первом блоке try-catch ваше исключение будет отловлено, оно не будет перехвачено внешним блоком catch. Однако, если он не будет перехвачен внутренним блоком catch, он попытается найти соответствующий обработчик исключений во внешнем блоке catch.

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

Например, этот код:

try
{
    try
    {
        throw std::runtime_error("Test");
    }
    catch (std::runtime_error& e)
    {
        std::cerr << "Inner Exception-Handler: " << e.what() << std::endl;
        throw;
    }
}
catch (std::exception& e)
{
    std::cerr << "Outer Exception-Handler: " << e.what() << std::endl;
}

Результатом будет:

Inner Exception-Handler: Test
Outer Exception-Handler: Test

Это работает, потому что std :: runtime_error является производным от std :: exception . Следует также отметить, что в таком тривиальном примере также можно просто записывать блоки catch друг за другом, но если вы хотите выполнить другой код после первого блока catch, вам придется их вкладывать.

6 голосов
/ 16 февраля 2009

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

Еще один способ справиться с этим - использовать несколько блоков catch.

void f()
{
    try
    {
        //Some code that throws ExceptionA
        //Some code that throws ExceptionB
    }
    catch(ExceptionA ea)
    {
        //Some exception handling
    }
    catch(ExceptionB eb)
    {
        //Some exception handling
    }
}//f

Здесь следует соблюдать особую специфику типов исключений в ваших блоках перехвата. Если ExceptionB расширяет ExceptionA в приведенном выше примере, тогда блок ExceptionB никогда не будет вызван, потому что любой генерируемый ExceptionB будет обработан блоком ExceptionA. При работе с иерархиями классов исключений необходимо упорядочивать блоки перехвата в наиболее специфическом или наименее конкретном порядке.

1 голос
/ 16 февраля 2009

Это законно, но не так уж и полезно, если только вы не выбрасываете исключение из вашего внутреннего catch (). Например, вы можете захотеть перехватить исключение системного уровня, но для ясности кода выбросите свой собственный объект исключения.

1 голос
/ 16 февраля 2009

Да, вы можете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...