Подтвердить что ты не робот

Нет фигурных скобок вокруг main() - почему это работает?

Я работаю над книгой на С++, а в главе об ошибках у нее есть эта программа (я оставил несколько второстепенных вещей, но в основном это):

int main()
try { 
        // our program (<- this comment is literally from the book)
        return 0;
}
catch(exception& e) {
    cerr << "error: " << e.what() << '\n';
    return 1;
}
catch(...) {
    cerr << "Unknown exception\n";
    return 2;
}

Это скомпилировано, но, конечно, оно ничего не делало, поэтому мне все еще интересно о

  • Почему нет набора фигурных скобок, закрывающих все после main()? Являются ли блоки или я называю их "фразами" (ha!) Частью main() или нет?
  • Если они являются функциями, как там нет "int" перед уловом (что угодно)?
  • Если они не являются функциями, каковы они?
  • re catch (...), я никогда не видел, чтобы эллипсы использовались именно так. Могу ли я использовать эллипсы где угодно, чтобы означать "что угодно"?
4b9b3361

Ответ 1

1 почему нет набора фигурных скобок, закрывающих все после main()?...

Существует только ключевое слово try перед открывающей скобкой, а некоторые catch блокируют после конца main.

... Являются ли блоки или я называю их "фразами" (ha!) частью main() или нет?

2 Если они являются функциями, как там нет "int" перед уловом (что угодно)?

3 Если они не являются функциями, каковы они?

Они - ключевые слова, а не функции, и они являются частью основного, несмотря на try, идущий между определением int main() и телом {}. См. Мотивирующий случай ниже для другого примера.

4 re catch (...), я никогда не видел, чтобы эллипсы использовались именно так. Могу ли я использовать эллипсы где угодно, чтобы обозначить "что угодно"?

в С++ есть несколько перегруженных значений многоточия.

  • catch(...) означает "поймать что-либо", это как шаблон для типа исключения (и должен быть последним уловком, если у вас их несколько).
  • int printf(char *, ...) означает, что функция принимает список переменных аргументов, что полностью отключает проверку типов аргументов и легко ошибиться (но иногда полезно).
  • template <typename... TypePack> означает, что шаблон принимает список типов переменных, который очень полезен для метапрограммирования, но полностью выходит за рамки здесь.
  • #define DEBUG(str, ...) - это переменный макрос, аналогичный функции переменных-аргументов

Блоки уровня функций try/catch - это способ обертывания всего тела функции в обработчике исключений. Итак, здесь главный функциональный блок находится внутри try { ... }.

IIRC это было введено специально, чтобы позволить конструкторам обернуть свои списки инициализаторов с помощью try/catch, чтобы обрабатывать исключения, созданные из конструкторов субобъектов.

Eg. (мотивирующий случай)

C::C() try : Base(1), member(2)
{ ...
}
catch (...) {
    // handle Base::Base or member construction failure here
}

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

Ответ 2

Если вы используете блок try непосредственно вместо брекетов, блок try поймает все, что происходит в функции. Это полезно в конструкторах, поэтому вы можете перехватывать исключения в списке инициализации.

Это приведет к исключению из конструктора bar:

void Foo::Foo() try : bar() {
    // do something
} catch(...) {
    // do something
}

Это исключает только исключения в теле:

void Foo::Foo() : bar() {
    try {
        // do something
    } catch(...) {
        // do something
    }
}

Ответ 3

Это редко используемая функция языка. Вы можете заключить целую функцию в блок catch try:

void f()
try 
{         // function starts here
...
}         // function ends here
catch (...) 
{}

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

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

Ответ 4

Это function-try block. Да, это законно, но не нужно в большем числе случаев. Посмотрите на этот ответ для объяснений. В чем смысл этого синтаксиса?

Ответ 5

Не уверен в отсутствии фигурных скобок вокруг основной функции, но похоже, что другие ответили, что все готово.

Что касается остальной части вашего вопроса, попробуйте блокировки блокировки не являются функциями вне основного и не нуждаются в int перед ними.

try {}: программа попытается выполнить что-либо в этом блоке, если по какой-то причине она не сработает, она будет поймана блоками catch.

catch (exception) {}: Когда генерируется исключение, он будет пойман блоком catch с конкретным Исключением в качестве его параметра и позволит программисту обрабатывать этот случай.

catch (...) {}: следует улавливать все, что делает это через первый блок catch.

Ответ 6

1) Что функция С++, блок try-catch функции (см. здесь, например)
2) И да, catch(...) { /* absolutely any exception gets caught here */ }