《C++ Primer 第四版》笔记(5)


第五部分 高级主题
     
[第17章  用于大型程序的工具]
    通过异常我们可以将问题的检测和问题的解决分离。由问题检测部分抛出一个对象给处理代码,通过这个对象的类型和内容,两个部分能够就出现了什么错误进行通信。
    异常以类似于将实参传递给函数的方式抛出和捕获。异常可以是可传给非引用形参的任意类型的对象,这意味着必须能够复制该类型的对象。
    当抛出一个表达式的时候,被抛出对象的静态编译时类型将决定异常对象的类型。
    最好不要抛出指针,抛出指针要保证在对应处理代码存在的任意地方存在指针所指向的对象。不能抛出指向局部对象的指针。
    抛出异常后寻找处理代码并处理的过程称为栈展开(stack unwinding)。栈展开期间,将会释放局部对象所用的内存并运行类类型局部对象的析构函数。
    析构函数中不要抛出异常!!在为某个异常进行栈展开的时候,析构函数如果又抛出自己的未经处理的另一个异常,将会导致调用标准库terminate函数。一般而言,terminate将调用abort函数,强制从整个程序非正常退出。
    构造函数中可以抛出异常,而且经常可能会抛出异常。
    如果栈展开过程中找不到匹配的catch,程序将调用terminate函数。
    在查找匹配的catch时,只要找到一个匹配的catch就停止检验后续的catch是否匹配,因此找到的catch未必是最匹配的。因此catch块的顺序非常重要。通常将特殊的catch排在前面。
    除下面几种情况外,异常的类型必须与catch说明符的类型完全匹配:
(1)允许从非const到const的转换;
(2)允许从派生类到基类类型的转换;
(3)将数组转换为指向数组类型的指针,将函数转换为指向函数类型的适当指针。
    异常说明符类型必须可以是引用。
    异常对象本身是被抛出对象的副本。
    如果catch子句处理因继承而相关的类型的异常时,通常将异常说明符类型定义为引用,这样可以利用多态性,基类可以调用派生类对象的函数。
    带有因继承而相关的类型的多个catch子句时,应将派生类类型的处理代码放在基类类型处理代码之前,否则会调用首先匹配的基类类型,派生类类型处理代码得不到执行。
可以用空的throw;语句在catch块内重新抛出异常。被抛出的异常是原来的异常对象,而不是catch形参类型。如果catch形参是引用类型,且在catch块内throw;语句前改变了异常对象,则重新抛出的对象将是修改过的。
可以定义catch(…){//异常处理代码} 来处理所有类型的异常。通常这样的catch块排在所有catch块的最后。
为了处理构造函数初始化列表中抛出的异常,应该将构造函数编写为函数测试块(function try block),将一组catch子句与函数联成一个整体。
如果局部动态分配了内存,而在释放内存前抛出了异常,则局部内存将无法正确释放。为了正确释放这类内存,可以采用“资源分配即初始化”(RAII)这种技术。可以设计专门的一个类用于资源管理,抛出异常时编译器将会调用析构函数释放内存;也可以用标准库的auto_ptr类。auto_ptr类是接受一个类型形参的模板,它为动态分配的对象提供类型安全。
命名空间可以在全局作用域或者其他作用域中定义,但不能在函数或类内部定义。
命名空间作用域的定义最后没有分号。
命名空间的定义可以是不连续的,可以在一个文件多个地方或者在多个文件中定义同一个名字命名空间,它们的定义是累积的。
定义在全局作用域(在任意类、函数或者命名空间外部)中的名字定义在全局命名空间中。全局命名空间是隐式声明的,它没有名字,可以用::member_name的形式显式引用。
未命名的命名空间的定义局部于定义文件,不跨越多个文件。
using声明:using std::map; using声明可以出现在全局作用域、局部作用域或者命名空间作用域中。类作用域中的using声明局限于被定义类的基类中定义的名字。
可以定义命名空间别名:namespace primer = cplusplus_primer;
using指示:using namespace iostream; 最好不要用using指示的方式,这种方式使得指定命名空间中的所有成员可见,这样很可能造成名字冲突,使得全局命名空间污染问题重新出现。使用using指示带来的名字冲突问题只有在名字使用时才能检测出来。推荐使用类似于using std::map; 这种using声明的方式,这样可以把名字冲突的可能性降到最小,而且名字冲突在声明处即可检测出来,而不是在使用时才能检测。
在多重继承中,多个基类的调用顺序是由派生列表中的出现次序确定的,而不是构造函数初始化列表中的顺序。
与单继承类似,多重继承的析构函数只负责清理本类新加的信息,复制构造函数和赋值操作符则需要负责所有基类的子部分。
如果一个派生类的多个直接或间接基类具有相同名字的成员,则用派生类直接引用该成员时将造成二义性。即使两个基类的函数名字相同但形参表不同也会编译报错。即使一个同名的成员在一个类中是私有的而在其他类中是公有或保护的,也会编译报错。这种情况下,派生类中引用需要显式指定到底是引用哪个基类的成员,如c.B::print();
用虚继承的方式来解决一个基类在同一派生类中出现多个子对象的问题。如果使用了虚继承,则派生类的构造函数除了要调用直接基类的构造函数外,还需要调用虚基类的构造函数。
    无论虚基类出现在继承层次中任何地方,总是在构造非虚基类之前构造虚基类。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值