9.3.3 为何所有的析构函数都应该声明为 virtual 的? 如果使用delete删去一个实际指向派生类的基类指针,析构函数调用链就被破坏。这导致后面使用parent 的指针访问child 对象并删去对象时,就会出问题。 ( 需要深入理解,为什么?) 9.3.4 向上转换: Super mySuper = mySub;// SLICE; // 会截断; Super & mySUper = mySub; // OK, 不会截断 因此,向上转换的时候,需要使用指针或者引用

向下转换:dynamic_cast , 因为它可以使用对象内建的类型信息,拒绝没有意义的类型转换。如果转换失败,这个指针的值就是nullptr; 如果针对对象引用的dynamic_cast 失败,将抛出std::bad_cast 异常。

C++中,重写可以让子类的成员返回子类的对象的指针或者引用,它和父类中对应的函数是重载的;

如果需要载子类中利用父类的构造函数,可以用类似下面的using关键字去实现: using Super::someMethod; // Explicitly inherits the Super version

为类避免改变类基类的虚函数,而忘记修改类对应的函数继承链条上的子类中的函数,可以载实现重现函数的后面加上 “override” 关键字,这样就可以在编译截断就发现问题。

Typid:这个运算可以在运行时查询对象,从而判断对象的类型; Dynamic_cast 不能在没有虚方法的类上使用; 析构函数一定要是虚函数,否则可能导致子类的资源无法释放; 如何实现virtual 编译的时候,如果某个类中有虚函数,就需要创建vtable,这个表中包含类指向虚方法实现的指针。

10.1

10.1.1 关于引用 放在类型后: 只能初始化一次,指向被引用的对象: 声明的时候初始化; 调用的时候被改变值;

作为参数: 避免复制参数的所有内容; 可以直接修改引用指向的内容;

作为返回值: 避免值拷贝; 返回的不是临时值,可以连续用返回值连续调用或者给返回值赋值;

(用返回左值引用的函数初始化一个新对象,和用移动拷贝或构造函数基于右值去初始化一个对象的效率是一样高的,都没有拷贝) 10.1.2 constexpr 关键字 编译器必须在编译期间对constexpr函数求值,因此不允许有任何副作用。下面是几个限制: 函数体就是一个 return 语句; 返回类型应该是字面量类型,返回值不能是void; 函数的所有参数都应该是字面量类型;

*右值引用 STL中的swap()很多是基于右值引用实现的,(自己写一个) 对于返回(使用)右值引用的函数需要加上 noexpect

11.1 IO流 检查流的状态: good(): bad(): fail(): tell(): Seekg(): 移到输入流指定偏移的位置; Seekp(): 移到输出流指定偏移的位置;

\n 仅仅开始一个新行,而endl 还会刷新缓冲区; 如果需要把类的内部信息都输出,可以重载《输出符号;

流的两种经典使用方法: 方式一:将不同文件的流连在一起 ifstream inFile(“input.txt”); ofstream outFile(“output.txt”); inFile.tie(&outFile); outFile << “Hello “; string nextToken; inFIle >> nextToken; 注意:此时读inFile的时候,因为关联写入的“Hello”才能从cache中刷出; 引用:从cin 读入数据的时候,cout会同步输出;

方式二:同时实现双向IO fstream 类; fstream ioData(inFIleNmae.c_str());