main()周围没有花括号 - 为什么这有效?

时间:2012-08-03 18:29:29

标签: c++ syntax error-handling

我正在编写一本关于C ++的书和关于它有错误的章节(我留下了一些小问题,但主要是这个):

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;
}

这已编译但当然没有做任何事情,所以我仍然想知道

  1. 为什么在main()之后没有一组花括号括起来?是块还是我称之为“流行语”(哈!)是main()的一部分还是没有?
  2. 如果它们是函数,那么在catch之前没有“int”(无论如何)?
  3. 如果它们不起作用,它们是什么?
  4. 重新捕捉(...),我从未见过这样使用的椭圆。我可以在任何地方使用省略号来表示“任何东西”吗?

6 个答案:

答案 0 :(得分:15)

如果直接使用try块而不是大括号,try块会捕获函数中发生的所有内容。这在构造函数中很有用,因此您可以在初始化列表中捕获异常。

这将捕获bar的构造函数的异常:

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

这只会捕获正文中的异常:

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

答案 1 :(得分:10)

  

1为什么在main()之后没有一组花括号括起来? ...

在开始大括号之前只有关键字try,而在catch结束后 后会有一些main阻止

  

......这些街区或我是否应该将它们称为“流行语”(哈!)是否是主要()的一部分?

     

2如果它们是函数,那么在catch之前没有“int”(无论如何)?

     

3如果它们不起作用,它们是什么?

它们是关键字,而不是函数,尽管try定义与其int main()正文之间存在{},但它们仍然是主要的一部分。有关其他示例,请参阅下面的激励案例

  

4重新捕捉(...),我从未见过用这种方式使用的椭圆。我可以在任何地方使用省略号来表示“任何东西”吗?

在C ++中有一些重载的省略号含义。

  • catch(...)表示捕获任何,它就像异常类型的通配符(如果你有几个,应该是最后一个捕获)
  • int printf(char *, ...)表示函数采用变量参数列表,它完全禁用参数的类型检查,很容易出错(但偶尔会有用)
  • template <typename... TypePack>表示模板接受变量 type 列表,这对于元编程非常有用,但完全超出范围
  • #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 :(得分:10)

这是该语言很少使用的功能。您可以将整个函数包含在try catch块中:

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

该功能很少使用,因为它几乎从未有用。在常规函数的情况下,您可以只使用覆盖函数所有代码的try / catch块,因此在这种情况下不需要该功能。它在构造函数中具有有限的功能,因为它允许捕获初始化程序列表中的异常,否则不能将其包含在try / catch块中。

但问题是在catch块中可以做的很少:构造失败,因此必须抛出 异常(catch块可以对捕获的内容抛出不同的异常,但它投掷)。同时,你不能真正执行任何清理,因为在捕获异常的时候你可能不知道初始化列表中的哪些元素丢了,这意味着你可能不知道(在一般情况下)哪个成员对象是否已构建。

答案 3 :(得分:2)

这是function-try block。是的,这是合法的,但在更多情况下不需要。看看这个答案的解释。 What is the meaning of this syntax?

答案 4 :(得分:2)

不确定主要功能周围是否缺少花括号,但看起来其他人都回答说准备好了。

至于你的问题的其余部分,try catch块不是main之外的函数,并且不需要在它们前面有int

try {}:程序将尝试在此块中运行任何内容,如果由于某种原因失败,它将被catch块捕获。

catch (exception) {}:当抛出异常时,它将被一个具有特定Exception作为参数的catch块捕获,并允许程序员处理该情况。

catch (...) {}:应该抓住任何通过第一个捕获块的东西..

答案 5 :(得分:0)

1)这是C ++的一个特性,功能试试块(例如,参见here
2)是的,catch(...) { /* absolutely any exception gets caught here */ }