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

agyaoht7  于 2023-01-22  发布在  其他
关注(0)|答案(2)|浏览(110)

我遇到过一个例子(对于一个微不足道的函数try块),它似乎利用了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;
    }
};

原作者突然在一个例子中加入了这个语法,我想知道这样的语言构造的含义

cqoc49vn

cqoc49vn1#

XXX:是一个标签,它在你发布的代码中没有任何功能,它可能是作者为了帮助他们组织代码而添加的。
您可以在后藤语句中使用标签,如在goto XXX;中,以跳转到代码中的那个点,尽管我将由您来决定这是否是一个好主意。

rseugnpd

rseugnpd2#

foo::foo()
try
{
body:
   //... do stuff that could possibly throw
}
catch(std::exception &e){
handler:
   throw;
}

这段代码有两个相当不寻常的构造,第一个是你已经指出的,并且在mjk的回答中已经解释过了:bodyhandler是标签。标签用于goto,而goto又可用于流控制(决定代码应该在哪里继续执行)。现在,goto应该很少使用,因为很少有其他流控制不能替代它们的情况(ifforwhiledo...)这将使它更具可读性。由于goto s很少使用,标签也很少使用。
第二个有趣的构造是函数级try块:

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

相关问题