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

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 { };

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值