Вопросы относительно порядка операторов catch в блоке catch - для конкретного компилятора или стандарта языка? - PullRequest
5 голосов
/ 09 марта 2010

В настоящее время я использую Visual Studio Express C ++ 2008, и у меня есть несколько вопросов о порядке упорядочения блоков. К сожалению, я не смог найти ответ в Интернете, поэтому я задаю эти вопросы экспертам.

Я заметил, что если catch (...) не помещен в конец блока catch, компиляция завершится с ошибкой C2311. Например, будет скомпилировано следующее:

catch (MyException)
{
}
catch (...)
{
}

в то время как следующее не будет:

catch (...)
{
}
catch (MyException)
{
}

а. Могу я спросить, определено ли это в стандарте языка C ++, или это строгий компилятор Microsoft?

б. C # и Java имеют одинаковые правила?

с. Кроме того, я также попытался создать базовый класс и производный класс и поместить оператор catch для базового класса перед оператором catch для производного класса. Это составлено без проблем. Пожалуйста, не существует ли языковых стандартов, защищающих от такой практики?

Ответы [ 3 ]

5 голосов
/ 09 марта 2010

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

a) Поскольку catch(...) сделает любые последующие уловы неактуальными, стандарт допускает только последний улов.

b) C # и Java имеют похожие правила.

c) перехват (по ссылке или указателю) базы до того, как производный класс сделает код для производного неактуальным. Тем не менее, стандарт допускает это

3 голосов
/ 09 марта 2010

Так называемый обработчик по умолчанию catch(...) должен быть последним обработчиком в списке обработчиков. Это действительно требуется стандартом. Однако это требование относится к обработчику по умолчанию.

В противном случае стандарт не ограничивает упорядочение обработчиков, что означает, что обычно вы можете создать обработчик, который «перехватит» все исключения, которые в противном случае достигли бы какого-либо другого обработчика в списке (таким образом, делая последний обработчик бесполезным).

Более того, совершенно законно повторять одно и то же предложение catch (с одним и тем же типом) несколько раз

catch (int) {
  // ...
}
catch (int) {
  // ...
}

, хотя только первый сможет поймать что-нибудь. Хороший компилятор выдаст предупреждение для подобных случаев, но формально это не ошибка.

3 голосов
/ 09 марта 2010

Из стандарта C ++ 15.3 / 5 «Обработка исключений»:

Обработчики для блока try пробуются в порядке появления. Это позволяет писать обработчики, которые никогда не могут быть выполнены, например, помещая обработчик для производного класса после обработчика для соответствующего базового класса.

A ... в объявлении-исключении обработчика функционирует аналогично ... в объявлении параметра функции; это определяет соответствие для любого исключения. Если присутствует, обработчик ... должен быть последним обработчиком для его блока try.

...