2010-03-08 1 views
5

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

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

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

, а следующий не будет:

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

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

b. У C# и Java есть те же правила?

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

+0

Re (B): раздел 8.10 спецификации C# дает подробное описание того, как это работает на C#. См. Подробности. Re (C), который является незаконным в C#. Подробности см. В разделе 8.10. –

ответ

5

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

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

b) C# и Java имеют аналогичные правила.

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

+0

a) истинно (первые два предложения). catch (...) имеет специальную обложку, потому что более поздняя статья никогда не может сравниться, поэтому более поздние статьи полностью запрещены. –

+0

Отзыв по этим двум комментариям. Спасибо Johannes и Ben –

3

От C++ стандарт 15,3/5 «Обработка исключения»:

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

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

+1

Любая идея, почему стандарт не запрещает это? Похож на тупую ловушку, которую легко избежать, сделав ее неформальной. –

+0

Майкл, спасибо за ваш ответ. Йоханнес, спасибо за вопрос - это то, что мне интересно. – Andy

+0

@litb: понятия не имею. Мне будет интересен комментарий от любого, кто может знать (или имеет хорошее предположение). –

3

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

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

Кроме того, это совершенно законно, чтобы повторить тот же catch пункт (с тем же типом) несколько раз

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

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

+0

Спасибо. Я не знал, что вы можете иметь две команды catch, которые вылавливают точно такой же тип данных! – Andy