Naw*_*waz 36 c++ function function-try-block
我想知道程序员何时使用函数try块.什么时候有用?
void f(int i)
try
{
   if ( i  < 0 ) 
      throw "less than zero";
   std::cout << "greater than zero" << std::endl;
}
catch(const char* e)
{
    std::cout << e << std::endl;
}
int main() {
        f(1);
        f(-1);
        return 0;
}
输出:(在ideone处)
greater than zero
less than zero
编辑:因为有些人可能认为函数定义的语法不正确(因为语法看起来不熟悉),我要说它不是不正确的.它叫做function-try-block.参见C++标准中的§8.4/ 1 [dcl.fct.def].
Ale*_* C. 27
您可以在构造函数中使用它来捕获初始化程序中的错误.通常,您没有捕获这些错误,因此这是一个非常特殊的用途.
否则,它是无用的:除非我被证明是错的,
void f() try { ... } catch (...) { ... }
严格等同于
void f() { try { ... } catch (...) { ... } }
hka*_*ser 12
函数try块在两个上下文中对我有用.
a)有一个catch all子句main()允许编写小实用程序而不必担心本地错误处理:
int main()
try {
    // ...
    return 0;
}
catch (...) {
    // handle errors
    return -1;
}
这显然只是在内部尝试/捕获的语法糖main().
b)处理基类构造函数抛出的异常:
struct B {
     B() { /*might throw*/ }
};
struct A : B {
     A() 
     try : B() { 
         // ... 
     } 
     catch (...) {
         // handle exceptions thrown from inside A() or by B() 
     } 
};
除了提到的功能用途之外,您还可以使用function-try-block来保存一个级别的缩进.(Ack,关于编码风格的答案!)
通常你会看到函数try-block的例子,如下所示:
void f(/*...*/)
try {
   /*...*/
}
catch(/*...*/) {
    /*...*/
}
函数作用域缩进到与没有函数try-block相同的级别.这在以下情况下非常有用:
git blame -w.)但是,对于完全用函数try-block包装的函数,我建议不要使用函数try-blocks在某些函数之间交替,而不要在同一代码库中交替使用.一致性可能比换行问题更重要.:)
如果要从构造函数的初始化程序中捕获异常,这可能很有用.
但是,如果您在构造函数中以这种方式捕获异常,则必须重新抛出它或抛出新异常(即,您不能通常从构造函数返回).如果你不重新抛出,它就会隐含地发生.
#include <iostream>
class A
{
public:
  A()
  try {
    throw 5;
  }
  catch (int) {
    std::cout << "exception thrown\n";
    //return; <- invalid
  }
};
int main()
{
  try {
    A a;
  }
  catch (...) {
    std::cout << "was rethrown";
  }
}
关于函数 try 块如何操作的注意事项:
对于构造函数,函数 try 块包含数据成员和基类的构造。
对于析构函数,函数 try 块包含数据成员和基类的析构。它变得复杂,但对于 C++11,您必须noexcept(false)在析构函数(或基/成员类的)的声明中包含,否则任何销毁异常都将导致在 catch 块结束时终止。可以通过return在 catch 块中放置一条语句来防止这种情况(但这对构造函数不起作用)。
构造函数或析构函数中的 catch 块必须抛出一些异常(否则它会隐式地重新抛出捕获的异常)。简单地return(至少在构造函数的函数 catch 块中)是不合法的。但是请注意,您可以调用exit()或类似的方法,这在某些情况下可能是有意义的。
catch 块不能返回值,因此它不适用于返回非 void 的函数(除非它们故意用exit()或类似的方式终止程序)。至少这是我读过的。
构造函数尝试的 catch 块不能引用数据/基成员,因为它们将 1) 未构造或 2) 在捕获之前被破坏。因此,函数 try 块对于清理对象的内部状态没有用——当你到达那里时,对象应该已经完全“死了”。 这个事实使得在构造函数中使用函数 try 块变得非常危险,因为如果你的编译器没有标记它,随着时间的推移很难监管这个规则。
有效(合法)用途
您可以使用它们的另一件事是在调试期间以不干扰完成的构建的方式提供额外的数据。我还没有看到其他人使用或提倡它,但我发现它很方便。
// Function signature helper.
#if defined(_WIN32) || defined(_WIN64)
    #define FUNC_SIG __FUNCSIG__
#elif defined(__unix__)
    #define FUNC_SIG __PRETTY_FUNCTION__
// Add other compiler equivalents here.
#endif  /* Function signature helper. */
void foo(/* whatever */)
#ifdef     DEBUG
try
#endif  /* DEBUG */
{
    // ...
}
#ifdef     DEBUG
catch(SomeExceptionOrOther& e) {
    std::cout << "Exception " << e.what() << std::endl
              << "* In function: " << FUNC_SIG << std::endl
              << "* With parameters: " << /* output parameters */ << std::endl
              << "* With internal variables: " << /* output vars */ << std::endl;
    throw;
}
#endif  /* DEBUG */
这将使您既可以在测试代码时获得有用的信息,又可以轻松地对其进行模拟,而不会影响任何内容。