带有函数体的C++冒号语法

C++ colon syntax with function body

本文关键字:语法 C++ 函数体      更新时间:2023-10-16

我遇到了一个例子(对于一个琐碎的函数try块),从中似乎利用了C++语法中一个更模糊的方面(就像该语言的大多数模糊方面一样),我似乎找不到文档。

我在谷歌上搜索过,但没有结果,所有搜索都只返回(相当无用)构造函数初始化(我很熟悉),但我想知道的是这个构造函数块中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的回答中已经解释过:bodyhandler是标签。标签用于goto,然后可以用于流控制(确定代码应该在哪里继续执行)。现在,goto应该很少使用,因为在极少数情况下,它们不能被其他流控件(ifforwhiledo…)取代,从而使其更具可读性。由于goto很少使用,因此标签也很少使用。

第二个有趣的构造是函数级尝试块:

foo::foo()
try {
} catch (std::exception const &) {
}

请注意,try catch不是构造函数主体内部的,而是{}外部的。这也是一个罕见的构造。它被设计为支持在构造函数中的初始值设定项列表的求值过程中捕获异常(在上面的代码中,这是隐式的)。如果该类型有一个基,或者其构造函数可以抛出的成员,则永远不会对构造函数的主体进行求值,并且常规的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();
}