您的位置:首页 > 编程语言 > C语言/C++

C++ 学习笔记(18)异常处理(noexcept说明符和noexcept运算符、构造函数的try和catch)、命名空间(using声明和using指示)、多继承(虚继承)

2018-02-23 01:12 821 查看

C++ 学习笔记(18)异常处理(noexcept说明符和noexcept运算符、构造函数的try和catch)、命名空间(using声明和using指示)、多继承(虚继承)

参考书籍:《C++ Primer 5th》

C++ 学习笔记(5)语句、异常

18.1 异常处理

18.1.1 抛出异常

析构函数中,对于可能抛出异常的操作,必须放在try块中,并得到处理。否则在析构函数抛出异常时,程序会直接终止。

异常对象:使用异常抛出表达式对异常对象进行拷贝初始化。

表达式如果是类类型,必须含有可访问的析构函数、可访问的拷贝或移动构造函数。

表达式是数组或函数类型,会被转换成对应的指针。

异常处理完毕后,异常对象会被销毁。

18.1.2 捕获异常

如果catch接受的异常与某个继承体系有关,则最好将catch的参数定义成引用类型。

异常的类型和catch声明的类型是精确匹配的:

允许非常量转换成常量。

允许派生类转向基类。

数组和函数转换成对应指针。

其他都不能匹配(包括算术类型转换,类类型转换)。

重新抛出(rethtowing):catch语句中再抛出异常(直接一句
throw;
,不含表达式)。用于将异常传递给另一个catch继续处理。

捕获所有异常:
catch(...)
,必须出现在所有catch组合之后。

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

要处理构造函数的初始值抛出的异常,将构造函数写出函数try语句块(函数测试块)的形式。

A::A() try : value(123) { } catch ( const runtime_error  &e) { }
// 将 try 写在初始化列表之前,在函数体后添加catch语句块。


18.1.4 noexcept 异常说明

如果确认函数不会抛出异常,就可以执行某些特殊的优化操作。

不知道如何处理异常时,也可以声明noexcept。

如果函数声明了不抛出异常,但还是抛出了,程序会调用terminate确保不在运行时抛出异常的承诺。

// noexcept 说明符 : 跟在函数列表之后
void func() noexcept;
void func() throw();        // 等价上面

void a() noexcept(true);    // a不会抛出异常
void b() noexcept(false);   // b可能抛出异常

// -----
// noexcept 运算符: 与bool实参出现
bool bv = noexcept(a());    // 因为a不会抛出异常,所返回值为true
noexcept(e);        // 判断e对象的所有函数是不是都不抛出异常且不含有throw。


函数指针有noexcept说明符时,指向的函数也必须有。

虚函数有noexcept时,派生的虚函数也必须用。

18.1.5 异常类层次



运行时错误:程序运行时才能检测到。

逻辑错误:程序代码中的错误。

18.2 命名空间

18.2.1 命名空间定义

内联命名空间:可以直接被外层命名空间使用。关键字inline必须出现在命名空间第一次定义的地方。

namespace AAA
{
namespace BBB { int i; }
inline namespace CCC { int j; }
}

void main()
{
AAA::BBB::i;    // 必须写出所在命名空间
AAA::j;         // 可以直接访问内联命名空间
}


未命名的命名空间:拥有静态生命周期:在第一次使用前创建,直到程序结束后销毁。仅在特定文件内部有效,作业范围不会横跨多个不同文件。

静态声明:将名字声明成static使其对于整个文件有效,用未命名的命名空间实现。

namespace local
{
namespace
{
int i;
}
}

local::i =123;  // 直接使用。


namespace ABC { namespace EFG {} }
namespace A_G = ABC::EFG;       // A_G为命名空间ABC::EFG的别名


using声明:一次只引入命名空间的一个成员。如
using std::cout;


using指示:无法控制哪些名字可见,因为都可见。如
using namespace std;


18.3 多重继承与虚继承

18.3.1 多重继承

如果从多个基类继承了相同的构造函数(形参列表相同),会产生错误。

struct D : Base1, Base2
{
D(int i) : Base1(i), Base2(i) { }   // 对于相同的基类构造函数,需要自定义
}


18.3.4 虚继承

派生类可以多次继承同一个类。会产生多个子对象。

虚基类子对象:被虚继承的基类。在派生类中不管出现几次,都只包含唯一一个共享的虚基类子对象。

class B : virtual public A { }; // virtual 和 继承声明位置可以互换
class B : public virtual A { };
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: