[第一章 预备知识]
- 意大利面式编程(FORTRAN、BASIC)→结构化编程(C)→面向对象编程(C++)→泛型编程(C++)
- 结构化编程反应了过程性编程思想,两个原则:将分支(决定接下来应执行哪个指令)限制为一小组行为良好的结构;自顶向下的设计。
-
过程性编程 OOP 泛型编程 强调算法 强调数据 强调独立于特定数据类型 试图使问题满足语言的过程性方法 试图让语言来满足问题的要求 提供执行常见任务(如排序)的工具 - OOP理念:设计与问题的本质特性相对应的数据格式。
- 名称C++来自C语言中的递增运算符++
- 标准版本:《The Programming Language》→《The Annotated C++ Reference Manual》→C++98→C++03(没有改变语言特性,可与C++98视为同一版本)→C++11
[第二章 开始学习]
- "\n"和endl的区别:endl确保程序继续运行前刷新输出(将其立即显示在屏幕上);而使用“\n”不能提供这样的保证,这意味着在有些系统中,有时可能在您输入信息后才会显示。
[第三章 处理数据]
- C++标准中变量名长度没有限制,但有些平台有长度限制;而ANSI C只保证变量名中前63个字符有意义。
- #define编译指令是C语言遗留下来的。C++有一种更好的创建符号常量的方法(使用关键字const)。
- 然而,有些头文件,尤其是那些被设计成可用于C和C++中的头文件,必须使用#define。
- 通用字符名
- C++标准中变量名长度没有限制,但有些平台有长度限制;而ANSI C只保证变量名中前63个字符有意义。
- #define编译指令是C语言遗留下来的。C++有一种更好的创建符号常量的方法(使用关键字const)。然而,有些头文件,尤其是那些被设计成可用于C和C++中的头文件,必须使用#define。
- 定义符号常量,const比#define好的3个理由:
2. 可以将定义限制在特定的函数或文件中;
3. 可以用于更复杂的类型(如数组和结构)。
- signed char和unsigned char
- wchar_t
- char16_t和char32_t
- 浮点数之所以称为“浮点”,是因为可以通过小数点的移动缩放数的大小。
[第四章 复合类型]
-
cin.getline(char数组, 数组长度) 读取一行 cin.get(char数组, 数组长度) 读取一行,不读换行符 cin.get() 读一个字符 - C++在声明结构变量时可以省略关键字struct
- C++结构中是可以包含函数的,但一般就定义成类了
[第五章 循环和关系表达式]
- 用户定义类型前缀递增效率高
- 逗号表达式的顺序和值
[第八章 函数探幽]
- 如果使用C语言的宏执行了类似函数的功能,应考虑将它们转换为C++内联函数。
- 引用作为函数参数尽量用const没看懂
- 似乎没有深入探讨引用和指针的区别
- 函数的默认参数都放在参数略表的右边
- 编译器选择函数原型时的优先次序:非模板版本→显示具体化→模板版本
[第九章 内存模型和名称空间]
- volatile的作用
- mutable
- const全局变量的链接性是内部的
- 变量的声明区域、潜在作用域、作用域
- using声明 VS using编译指令
- 未命名的名称空间:可作为链接性为内部的静态变量的替代品
- 名称空间的使用原则
[第十章 对象和类]
- 定义位于类声明中的函数都将自动成为内联函数
- 不定义任何构造函数时C++才提供默认构造函数,否则需要自己定义不带参数的构造函数(如果需要的话)。
- const成员函数
- 要创建对象数组,这个类必须有默认构造函数。
[第十一章 使用类]
- 如果要为类重载运算符,并将非类的项作为其第一个操作数,则可以用友元函数来反转操作数的顺序。
定义中不加关键字friend
定义直接在类里时(内联)要加friend
- 类的隐式转换和显式转换
- 转换函数:用于将用户定义类型的对象显式或隐式地转换为基本数据类型,需在用户定义类中定义函数,详见P415。
- 静态数据成员的初始化
[第十二章 类和动态内存分配]
- 浅复制容易导致在对象析构时多次释放同一块内存(复制指针时)
- delete可与常规new运算符配合使用,不能与定位new运算符配合使用。使用定位new的对象需显示调用析构函数,
[第十三章 类继承]
- 成员初始化列表只能用于构造函数
- 基类的指针和引用可以直接指向派生类对象,但只能调用基类方法。
- 虚方法的作用
- 静态联编和动态联编
- 派生类声明与基类同名的方法将覆盖原方法而不是重载(即使其返回类型和参数列表不同)
- 保护访问控制protected
- 抽象基类(ABC):包含纯虚函数的基类。纯虚函数可以有定义。
- 派生类在构造函数中使用new时,需要显式定义析构函数、赋值构造函数、赋值运算符,否则不需要。
[第十四章 C++中的代码重用]
- 构造函数对成员的初始化顺序
- 私有继承:has-a关系
- 在派生类中使用using重新定义对基类成员的访问权限
- 【虚基类】
祖先相同的MI会导致重复的组件
- 使用虚基类的派生类构造函数怎么调基类构造函数?
[第十五章 友元、异常和其他]
- 在另一个类中声明的类称为嵌套类
- RTTI (Runtime Type Identification) 运行阶段类型识别
- C++之父Bjarne Stroustrup觉得C语言中的类型转换太松散(随意?),于是发明了4个类型转换的运算符:dynamic_cast、const_cast、static_cast、reinterpret_cast。
[第十六章 string类和标准模板库]
- C++ 11竟然摒弃了auto_ptr,原因见P670。
- 作为一种编程风格,最好避免直接使用迭代器,而应尽可能使用STL函数(如for_each())来处理细节。
- 五种迭代器的功能
-
STL C++ 概念(concept) 类 改进(refinement) 继承 模型(model) 实例/对象
- vector、valarray、array
[第十七章 输入、输出和文件]
- 缓冲区的作用
- UNIX只有一种文件格式,因此对它来说,二进制模式和文本模式是一样的。
- 内核格式化