zoukankan      html  css  js  c++  java
  • 第18章 用于大型程序的工具

    18.1异常处理

    try {
        // actions that cause an exception to be thrown
    }
    catch (...) {
        // work to partially handle the exception
        throw;
    }

    在C++中,通过throwing来raised一个exception。当throw时,throw后边的语句不再执行,转移到catch中,这意味:

    1. 沿着调用链的函数可能会提早退出
    2. 一点开始执行异常处理代码,沿着调用链创建的对象将被销毁
    3. 当throw一个exception时,会沿着函数调用链展开,寻找匹配的catch,如果没有找到,就会terminate。
    4. 展开过程中,对象被自动销毁
    5. 析构函数因为自动执行,所以外部无法捕获异常,他的异常应该在析构函数内部捕获并处理,如果没有处理,程序会terminate
    6. 抛出的对象如果是局部对象,将会因为展开过程中的自动销毁而不存在,抛出指针后所指向的对象必须保证存在。

    18.1.2捕获异常

    Catch中的异常声明,可以当成函数列表,如果使用可以为空。

    Catch中的异常对象如果非引用,将会发生拷贝

    特例的异常处理应该放在与异常最靠近的地方,一般的异常会截获特例

    在catch异常中,一般不允许类型转换(允许非const到const、派生类到基类、数组|函数转换到指针)

    在异常处理中,如果不能完全处理异常,可以再次抛出。

    Catch可以处理所有异常,可以使用【…】为参数

    18.1.3函数try语句块与构造函数

    要想处理构造函数初始值抛出的异常,必须将构造函数写成function try blocks,因为在构造初始值时(如下初始化data的时候),并未进入函数,所以在函数中无法处理,只能使用函数try语句块。(这个异常不能处理il构造时的异常)

    template <typenameT>
    Blob<T>::Blob(std::initializer_list<T> il) try :
        data(std::make_shared<std::vector<T>>(il)) {
        /* empty body*/
    }
    catch (const std::bad_alloc &e) 
    {
        handle_out_of_memory(e);
    }

    18.1.4异常说明noexcept

    1. 如果一个函数后有noexcept,表示这个函数不会抛出异常(声明和定义中都必须出现)。亦可以在一个函数指针的声明核定一种指定noexcept。
    2. 如果函数声明为noexcept,但是确实发生了异常,就会terminal,而并不会栈展开。

    判断一个调用是否是异常你一使用一元运算符noexcept(),并返回一个bool值指示是否会抛出异常。如果noexcept(true)放在一个函数后,表示此函数不会抛出异常,如果noexcept(false)放在一个函数后,表示此函数可能抛出异常。

    //如果g()确定不会抛出异常,返回true,则f()确定不异常
    void f() noexcept(noexcept(g()));

    异常说明与指针、虚函数和拷贝控制

    如果函数指针有noexcept说明符,则不能将没有noexcept声明的函数绑定到上边

    如果函数指针没有noexcept说明,则可以将任何函数绑定到上边。

    如果虚函数承诺了noexcept,则继承后的派生类也必须声明为noexcept

    对于合成的拷贝控制成员,如果其能够确定不会抛出异常,则合成的也是noexcept

    18.1.5异常类层次

    exception

    bad_alloc

    none

    logic_error

    domain_error

    invalid_argument

    out_of_range

    length_error

    runtime_error

    overflow_error

    underflow_error

    range_error

    bad_cast

    none

    自定义异常类

    class out_of_stock : public std::runtime_error 
    {
    public:
        explicit out_of_stock(const std::string &s) :
            std::runtime_error(s) { }
    };

    18.2命名空间

    //定义命名空间
    namespace my_namespace
    {
        //将其他空间中的成员在这里声明
        using std::cout;
        //命名空间别名
        namespace lib = std;
        void Foo()
        {
            //endl没有声明,必须写完整
            cout << "my namespace" << lib::endl;
        }
        //嵌套的命名空间,并且是内联的
        //内联的命名空间中的成员使用时不必完整写全
        inline namespace my_namespace_extends
        {
        }
    }
    class ClassName
    {
    };
    //模板特例化必须在原命名空间中
    namespace std
    {
        template <> struct hash<ClassName>;
    }
    //未命名的命名空间
    //其中变量拥有静态声明周期,第一次使用前创建,程序结束销毁
    //可以在一个文件中不连续,不能跨文件
    namespace
    {
    
    }

    18.2.3类、命名空间和作用域

    函数调用时,实参的命名空间会自动引入。

    18.3多重继承与虚继承

    1. 在某个给定的派生列表中,同一个基类只能出现一次。
    2. 派生类构造函数可以初始化它的直接基类。
    3. 派生类继承基类的构造函数,但是如果有多个基类中构造函数参数相同,则必须自定义这个构造函数,否则会出错。
    4. 如果一个函数重载对每个基类作为参数,则函数在派生类的对象做参数时,类型转换会有二义性错误
    5. 虽然派生列表中,一个基类可以出现一次,但是也可以通过间接多次继承同一个类。默认情况下,多次继承的类将对应多个独立的部分,存在于继承链的不同位置。
    6. 如果希望这个继承多次的类只对应一个部分,则使用虚继承。
    7. 但是需要注意,派生类继承时,其基类所对应的同一个间接基类之间的关系是虚拟继承时,才会实现虚继承。
      class Raccoon : public virtual ZooAnimal { /* ... */ };
      class Bear : virtual public ZooAnimal { /* ... */ };
      class Panda :Raccoon, Bear {/* ... */};
    8. 派生类的Panda需要独自控制其虚拟基类部分,如果Panda没有控制,则使用其默认构造函数,并且虚拟基类会首先被构造。
      class Panda :Raccoon, Bear
      {
          Panda(std::string name, bool onExhibit)
              :ZooAnimal(name, onExhibit, "Panda"),
              Bear(name, onExhibit),
              Raccoon(name, onExhibit),
              Endangered(Endangered::critical),
              sleeping_flag(false) { }
      };
    9. 析构函数是构造函数调用顺序的反序。
  • 相关阅读:
    IIS7中的几种身份鉴别方式(一)Basic身份验证
    IIS7中的几种身份鉴别方式(二)集成身份验证
    java集合
    SharePoint 2010中welcome page的设置细节
    SharePoint中使用Linq出现未将对象引用到实例化的解决方法
    SharePoint 2010中关于An error was encountered while retrieving the user profile的处理方式记录
    The Need for an Architectural Body of Knowledge
    The Softer Side of the Architect
    Event Receivers 学习小结
    使用SmtpClient发送带图片的邮件的代码实现
  • 原文地址:https://www.cnblogs.com/qiusuo/p/5154122.html
Copyright © 2011-2022 走看看