编程笔记001|C++中的异常机制与dynamic-创新互联

一、C++ 中的异常机制 (exceptions)
  1. 头文件cstdlib/stdlib.h包含:
    1. std::abort()可以向标准错误流cerr发送消息abnormal program termination, 然后终止程序.
    2. std::exit(...)/exit(...)刷新文件缓冲区而不显示消息.
  2. 常见异常机制:
    1. try表示注意该代码块引发的异常.
    2. throw类似跳转, 常见的是throw "...".
    3. catch (type)处理异常.
    4. 进阶版本:
      1. 可以throw一个类对象 (直接构造函数形式throw classname(x, y, ...)),catch中调用对象接口函数.
      2. 异常规范: 现在不常用. 剩下一个noexcept放在函数声明后面表示不会引发异常.
      3. 栈解退 (unwinding the stack):throw完之后层层栈解退, 直到到达try所在那层, 然后 “搜寻”catch. 与此同时自动变量, 对象会相应析构.

        throw语句将控制权向上返回给第一个满足如下条件的函数: 包含能够捕获相应异常的try-catch组合.

        创新互联公司服务项目包括金川网站建设、金川网站制作、金川网页制作以及金川网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,金川网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到金川省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
        • throw自动生成副本, 但仍然建议在catch中使用引用. 主要原因是可以执行派生类对象.
        • catch块的排列顺序应和类的派生顺序相反 (否则引用出问题).
    5. 头文件exception包含exception类, 用class classname: public std::exception可以使用其中的what()方法, 一般return一个字符串.
    6. 头文件stdexcept十分万能:
      1. logic_error系列
        1. domain_error: 函数定义域.
        2. invalid_argument: 传递的字符串出错.
        3. length_error: 空间不够 (e.g.数组).
        4. out_of_bounds: 索引无效.
      2. runtime_error系列
        1. range_error: 除了下面两者的所有.
        2. overflow_error: 超过变量类型大范围.
        3. underflow_error: 低于了浮点数最小表示值.
      3. bad_allocexception公有派生.
      4. std::nowthrow,std::nothrow.
  3. 异常何时出现问题
    1. 未捕获异常
      1. 调用terminate()函数. (头文件exception)
        1. terminate()默认调用abort()函数, 但可以通过set_terminate()函数修改行为 (但必须包含一个需调用的函数).
          typedef void (*terminate_handler)();
             terminate_handler set_terminate(terminate_handler f) throw();
             terminate_handler set_terminate(terminate_handler f) noexcept;
             void terminate();
             void terminate() noexcept;
      2. 调用unexpected()函数. 可用set_unexpected修改 (默认调用terminate).
    2. 一些不易引起注意的事项
      1. 如果用了new进行内存分配, 过早的终止会导致相应的delete语句不被执行, 导致内存泄漏.

        解决方案:

        • catch语句中加入相应的delete语句.
        • (后文会提到) 智能指针模板.
二、与异常机制相结合: 更安全的四种类型转换
  1. RTTI (Runtime Type Identification 运行阶段类型识别)
    1. 用途: 虚函数能够 “自动” 地知道某指针指向的对象类型, 并自动调用其方法, 而如果我们需要把这一功能 “解封装”, 那就要用到 RTTI.
    2. 实现
      1. Class1ptr* c1 = dynamic_cast(var): 只会告诉你转换是否安全, 但不会告诉你具体是什么类型. 不安全返回空指针. 配合if可以包含检验环节.

        另外几种常见的强制类型转换:

        • static_cast: 几乎与dynamic_cast相同, 但是没有错误检查机制. 同时dynamic_cast能够检查形如 “A 同时派生了 B 和 C, B 与 C 之间的类型转换 (返回nullptr)”, 但static_cast不行. 但static_cast还允许枚举类型和整型之间以及数值类型之间的转换。

          注: 这两种转换在开发人员进行安全保证的情况下还可以脱离类来转换 (int ->char, etc.).

        • reinterpret_cast: “近乎万能”, 不关心类的继承关系.

        • const_cast: 把常量指针 / 引用转换为非常量指针 / 引用 (好处是确保了大部分时候的安全性).

      2. typeid(用到头文件typeinfo) 重载了运算符==!=, 常见有:
        1. typeid(var1 / typename1) == typeid(var2 / typename2)
        2. typeid(varname).name()

        重要提示: 如果发现在扩展的if else语句中使用了typeid, 则应考虑是否应该使用虚函数和dynamic_cast.

参考文献:C++ Primer Plus, 6th edition
欢迎关注我的博客! Find me on GitHub: GitHub profile page Gitee account (under construction): Gitee site GitLab account (under construction): GitLab site Also find me on Luogu:Luogu profile 欢迎大家关注我,在项目上与我协作哦!

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前文章:编程笔记001|C++中的异常机制与dynamic-创新互联
分享地址:http://scyanting.com/article/dcssgs.html