本部分罗列了本章的难点或注意点,以便复习巩固或者回忆,关注私聊我可以免费领取pdf版C++ Primer Plus 第6版。
-
友元:友元函数、友元类、友元成员函数
-
友元类的声明(friend class className;)可以放在位于公有、私有或保护部分,所在位置无关紧要
-
使用友元成员函数要采用前项声明解决循环依赖,并把友元成员函数本身的类的函数定义放在友元函数存在的类之后
class Tv; class Remote{}; class Tv{}; //put Remote method definitions here
-
互为友元必须保证声明在前的类中的使用后者类的函数定义在后者类声明的后面,原型可在前面
-
共同的友元例子p610
-
嵌套类作用域特征表p613
-
模板中的嵌套类也能使用模板类型
-
abort()的原型位于头文件cstdlib中,其典型实现是想标准错误流(cerr)发送消息abnormal program termination(程序异常错误),然后终止程序,它还返回一个随实现而异的值,告诉操作系统处理失败
-
引发异常、使用处理程序捕获异常、使用try块
-
C++11摒弃了异常规范(用于告诉用户需要使用try块;让编译器添加执行阶段检查的代码),不推荐用
double harm(double a)throw(bad_thing); double marm(double) throw();
-
C++11新增关键字noexcept指出函数不会引发异常,有助于编译器优化代码
-
程序进行栈解退以回到能够捕获异常的地方时,将释放栈中的自动存储型变量。如果变量是类对象,将对该对象调用析构函数
-
throw语句将控制权向上返回到第一个这样的函数:包含能够捕获相应异常的try-catch组合
-
引发异常时编译器总是创建一个临时拷贝,即使异常规范和catch块中指定的是引用
class problem{}; void super()throw(problem){ ... if(oh_no){ problem oops; throw oops; //oops会释放,因此会创建一个拷贝 可以使用throw problem() } } try{ super(); } catch(problem &p){ ... }
-
引用有一个重要的特性:基类引用可以执行派生类对象
-
如果有一个异常类继承层次结构,应这样排列catch块:将捕获位于层次结构最下面的异常类的catch语句放在最前面,将捕获基类异常的catch语句放在最后面
class bad1{...}; class bad2:public bad1{}; class bad3:public bad2{}; void duper(){ if(oh_no)throw bad1(); if(rats)throw bad2(); if(drat)throw bad3(); } try{ duper }catch(bad3 &b){ }catch(bad2 &b){ }catch(bad1 &b){ }catch(...){ }
-
省略号可以用来表示异常类型,从而捕获任何异常
-
可以创建捕获对象而不是引用的处理程序,在catch语句中使用基类对象时,将捕获所有的派生类对象,但派生类特性将被剥夺,因此将使用虚函数的基类版本
-
C++如今让bad_alloc异常处理new导致的内存分配问题,头文件new包含bad_alloc类的声明,它是从exception类公有派生而来的
struct Big{ double stuff[20000]; } Big* pb; try{ pb = new Big[10000]; }catch(bad_alloc& ba){ cout<<ba.what(); //std::bad_alloc exit(EXIT_FAILURE); //#include <cstdlib> }
-
C++标准也提供了在失败时返回空指针的new
int *pi = new(std::nothrow) int; int *pa = new(std::nowthrow) int[500]; if(pi == 0){ exit(EXIT_FAILURE); }
-
RTTI旨在为程序在运行阶段确定对象的类型提供一种标准方式。dynamic_cast运算符将使用一个基类的指针来生成一个指向派生类的指针;否则,该运算符返回0——空指针。typeid运算符返回一个指向对象的类型的值。type_info结构存储了有关特定类型的信息。
class Grand{static void say();}; class Super:public Grand{void say();static void write();}; Grand *pg = new Grand; Grand *ps = new Superb; Super *pm = dynamic_cast<Super*>(pg); //return pm=0 pm->say(); //invalid pm->write();//invalid Super *pd = dynamic_cast<Super*>(ps); //return pd=ps; pd->say(); //Superb::say(); pd->write; //Super::write();
-
dynamic_cast也可以用于引用,但没有与空指针对象的引用值,用bad_cast异常来表示,它是从exception类派生而来的,在头文件typeinfo中定义的
#include <typeinfo> try{ Super &rs = dynamic_cast<Super &>(rg); }catch(bad_cast &){ ... }
-
typeid可接受类名和结果为对象的两种表达式,返回一个type_info对象的引用,type_info是在头文件typeinfo中定义的一个类,这个类重载了==和!=运算符。如果pg是空指针,将引发bad_typeid异常,它是从exception类派生而来的,在头文件typeinfo中声明的
typeid(Magnificent)==typeid(*pg); cout<<typeid(*pg).name();
-
const运算符用来改变值为const或volatile
High bar; const High* pbar = &bar; High *pb = const_cast<High *>(pbar); //pb可以修改bar的值 const High bar; //若指向的const,也不能修改
-
static_cast <type-name>(expression) 仅当type_name可被隐式转换为expression所属的类型或expression可被隐式转换为type_name所属的类型
-
reinterpret_cast
struct dat{short a;short b}; long value = 0xA224B118; dat *pd= reinterpret_cast<dat *>(*value); cout<<hex<<pd->a;
-
不能将指针指向更小的整型或浮点型,不能将函数指针转换成数据指针,反之亦然。