Я сталкивался с примером (для тривиальной функции-try-block), в котором, кажется, используется один из более неясных аспектов синтаксиса C ++, к которому (как и большинство неясных аспектов языка) я не могу найти документацию за.
Я искал Google безрезультатно, все поиски возвращали (довольно бесполезно) только для инициализации конструктора (с которой я знаком), но я хотел бы знать, насколько важна body:
а также handler:
операторы в этом блоке конструктора:
class foo{
foo() try
//initalizer list that could throw
{
body:
//do stuff that could possibly throw
} catch(std::exception &e) {
handler:
throw;
}
};
Оригинальный автор резко добавляет этот синтаксис в одном примере, и я хотел бы знать значение таких лингвистических конструкций
XXX:
это ярлык. Это не служит никакой функциональной цели в коде, который вы разместили. Возможно, автор вставил их, чтобы помочь им организовать код.
Вы можете использовать метки с операторами goto, как в goto XXX;
перейти к этому пункту в вашем коде, хотя я оставлю вам решать, будет ли это хорошая мысль или сейчас.
foo::foo()
try
{
body:
//... do stuff that could possibly throw
}
catch(std::exception &e){
handler:
throw;
}
Этот кусок кода имеет две довольно необычные конструкции. Первый — это то, что вы уже указали и уже объяснено в ответе mjk: body
а также handler
являются ярлыками. Метки используются для goto
s, и это, в свою очередь, может использоваться для управления потоком (определение, где код должен продолжать выполняться). Сейчас, goto
s следует использовать редко, так как очень мало случаев, когда они не могут быть заменены другими средствами управления потоком (if
,for
,while
,do
…) это сделало бы его более читабельным. поскольку goto
редко используются, этикетки также редко используются.
Вторая интересная конструкция — блок try на уровне функций:
foo::foo()
try {
} catch (std::exception const &) {
}
Обратите внимание, что там try
поймать не внутри тело конструктора, но на самом деле вне {}
, Это тоже редкая конструкция. Он был разработан для поддержки перехвата исключения во время оценки списка инициализатора в конструкторе (что в приведенном выше коде неявно). Если у типа есть база или члены, чьи конструкторы могут генерировать, тело конструктора никогда не будет оцениваться, и регулярный try-catch не будет полезен для обработки этого исключения. Блок try уровня функции также включает в себя список инициализаторов и будет перехватывать любые исключения, возникающие при вычислении конструкторов различных подчиненных. Это редко используемая конструкция, поскольку в catch
блок. Точное состояние того, что было или не было построено, неизвестно и не может быть проверено, поэтому единственно возможное использование — сбросить либо то же исключение, либо другое. Синтаксис в более полном примере:
T::T()
try
: base1(args), base2(), member1(), member2() //...
{
// body
} catch (exception1 const& ex1) {
// ...
throw; // rethrow same exception
} catch (exception2 const& ex2) {
// ...
throw different_exception();
}