IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 一个怪异的C++函数定义方式 -> 正文阅读

[C++知识库]一个怪异的C++函数定义方式

在阅读clickhouse代码的过程中,发现有一种函数定义形式很怪异,一度以为是代码写错了。。。


int?main()?
try
{
????XXX
}
catch?(DB::Exception?&?e)
{
????XXX
}

形式如上,函数名之后怎么能不加花括号呢?这是不是不符合语法?深入了解之后发现原来是我孤陋寡闻了。

https://en.cppreference.com/w/cpp/language/function-try-block

上面的代码其实跟下面差不多

int?main()?
{
????try
????{
????????xxx
????}
????catch?(DB::Exception?&?e)
????{
????????xxx
????}
}

第一种看起来比较怪异的形式在cpp里叫做function-try-block, 第二种就是我们常见的function-body

那么function-try-block主要使用于哪种场合呢?它是不是能捕获到所有的异常呢?让我们看下文档

The?primary?purpose?of?function-try-blocks?is?to?respond?to?an?exception?thrown?from?the?member?initializer?list?in?a?constructor?by?logging?and?rethrowing,?modifying?the?exception?object?and?rethrowing,?throwing?a?different?exception?instead,?or?terminating?the?program.?They?are?rarely?used?with?destructors?or?with?regular?functions.

Function-try-block?does?not?catch?the?exceptions?thrown?by?the?copy/move?constructors?and?the?destructors?of?the?function?parameters?passed?by?value:?those?exceptions?are?thrown?in?context?of?the?caller.

Likewise,?function-try-block?of?the?main()?function?does?not?catch?the?exceptions?thrown?from?the?constructors?and?destructors?of?static?objects?(except?for?the?constructors?of?function-local?statics).

function-try-block这种形式主要用于类构造函数和main函数中,而很少使用在类析构函数和其他常规函数中。

  • 在类的构造函数中,function-try-block能够捕获到初始化列表中的异常,用户可以在catch block中打印日志、修改异常、重抛异常。需要注意的是,function-try-block无法捕获传值参数的复制/移动构造函数/析构函数中抛出的异常,这些异常会传递到function-try-block调用者的上下文中。

  • 在main函数中,function-try-block能够捕获try块中的异常,但是无法捕获静态对象构造和析构过程中抛出的异常

相关实例如下所示:

#include?<exception>
#include?<iostream>

class?MyException?:?public?std::exception?
{
public:
????MyException(const?char*?msg)?:?msg(msg)?{?}
????virtual?const?char*?what()?const?throw()?{?return?msg.c_str();?}

private:
????std::string?msg;
};

class?M
{
public:
????explicit?M(size_t?size)
????{
????????throw?MyException("exception?from?constructor");
????}

????M(const?M?&?other)
????{
????????throw?MyException("exception?from?copy?constructor");
????}

????M(M?&&?other)
????{
????????throw?MyException("exception?from?move?constructor");
????}
????
????~M()
????{
????????//?throw?MyException("exception?from?destructor");
????}
};

class?A
{
public:
????explicit?A()?try:?
????????????m1(10),?
????????????m2(m1),?
????????????m3(std::move(m2))
????{
????}
????catch?(std::exception?&?e)
????{
????????std::cout?<<?"catch?exception?in?A:A:?"?<<?e.what()?<<?std::endl;
????????throw;
????}

????~A()?=?default;
private:
????M?m1;
????M?m2;
????M?m3;
};

int?main()
try
{
????A?a;
}
catch?(std::exception?&?e)
{
????std::cout?<<?"catch?exception?in?main:?"?<<?e.what()?<<?std::endl;
}

执行初始化列表m1(10)的时候会抛出异常,然后被A::A中的try catch捕捉到,重新抛出到main函数的上下文,接着被main中的try catch捕捉到。因此运行结果为

catch?exception?in?A:A:?exception?from?constructor
catch?exception?in?main:?exception?from?constructor
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-23 11:16:20  更:2021-09-23 11:16:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:28:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码