12.19学习

摸鱼了好几天了,今天想要狂雪,把primer整本搞完

话不多嗦,直接开始。

异常处理:

  1.异常处理当遇到throw语句时,沿调用链的函数可能会提早退出,并沿着调用链的对象将被销毁。

  重点:int* p = new int;之类的只能做到销毁int*,无法执行动态内存的销毁。

  *可以通过类的析构函数执行销毁(智能指针好用啊)

  无需访问抛出的异常时,可省略参数名 *catch(int*)

  2.静态类型决定了catch接受的异常类型!!!

  3.catch的匹配不一定是最佳的,而是至上而下的。

  4.catch的匹配机制十分严格,仅支持const转化,派生类向基类转化,数组指针,函数指针。

  5.空throw出现于处理语句内,代表重新抛出异常。这里注意一个点,若我们对异常对象做出某些处理,并且要让这个处理保留

  在重新抛出的异常中,在catch异常时候就要使用其的引用。

  6.try语句块与构造函数:

A(int x)try: data(x){
    
}
catch(...){

}

  try既能处理初始化列表发生的异常,也可以处理构造函数函数体执行时发生的异常。

  但需要注意的是,函数形参的初始化不归try管。

  7.noexcept函数中也可以抛出函数(违背承诺),当违背承诺发生时,程序会调用terminate.

  8.void foo() noexcept(true值)承诺不会抛出异常。

  9.noexcept除了当作说明符外,还是一个一元运算符。noexcept接受一个表达式,并判断它是否会抛出异常。

  这个在与上一条联用有很好的效果。

  10.函数指针也有是否有可能抛出异常被分为两类,两类指针不能互相转化。

  11.派生类继承虚函数时候,派生类虚函数的声明必须显式地做出相应的保证。

命名空间:
  1. namespace在它的作用域内要保持唯一,且namespace不能定义在函数或类的内部。

  2.namespace可以是不连续的,

namespace nsp{
}

  这既可以是定义一个新的命名空间,也可以是为已有的命名空间添加新的成员。

  所以我们可以把包含声明的命名空间定义在头文件中,在其他的源程序再添加命名空间中的成员的定义。

  一些问题与思考:

  inline func定义于namespace会发生什么?

  出了定义它的源文件,其他源文件并不能使用。

  class的定义为什么不能再源文件中?

  我琢磨了很久,应该是想出了一套比较好理解的解释方法。

  首先我们要先意识到一个点,如果我们在头文件”定义“一个类,不同于定义函数,这个头文件可以被多个源文件声明。

  我认为类的”定义“区别于一般对象的定义,类的”定义“没有产生任何实例产生,所以类的”定义“更类似于一种”声明“。

  在namespace里也是类似的,我们尽管对包含该namespace的头文件进行了多次的#include,但里面只是一堆声明,并不会产生任何不好的效果。

  我们可以注意到一个点,我们调用某个函数时,其实只是先需要他的声明,支持之后再给出定义。

  支持在其他源文件中定义这样的接口就是出于这样的原因。

  而类就不支持这样,我们在使用类来定义对象时,该类必须时完全的,所以不能将类的定义置于其他源文件中。

 

  

namespace floor1{
    inline namespace floor2{
       int x = 1;      
    }
}
cout<<floor1::x;

 

  inline namespace与普通namespace的唯一区别就是,inline无需通过namespace名来进行访问成员。

  一个特例,inline namespace如果在全局命名空间中,就无法与全局变量区分

  一个源文件的未命名命名空间只归该源文件所有,其名字可以直接使用,但同上也可能会跟包含的作用域的变量产生歧义。

 

  

 

  

  

  

 

上一篇:Java异常——2021-12-15


下一篇:你必须了解的Java异常知识