Part1、基础篇
变量和基本类型
- void main()是错的
/* c89 */
main();
int main(void);
int main(int argc, char *argv[]);
/* c99 */
int main(void);
int main(int argc, char *argv[]);
/*c++98*/
int main( )
int main(int argc, char *argv[])
PS:如果想让你的code可移植性更好,请一定要用int main !
-
标准I/O
- istream
A. cin - ostream
A. cout: 与cerr、clog:可重定向到文件
B. cerr: 不经过缓冲区,直接输出到屏幕
C. clog: 与cerr区别:经过缓冲区
?. 三者间的用途、区别
- istream
-
浮点型精度
- float:6位有效数字
- double:10位有效数字
- 双精度计算的代价极小(相对单精度),可忽略
- 甚至有些机器上,double计算比float要快
- Long double代价较高,所以首选double
-
初始化并不一定是赋值
- 直接初始化: int val ( 100 );
- 赋值初始化: int val = 100;
作用域和生存周期是不同步的
-
引用
- 引用定义时必须初始化
- 一旦绑定一个对象,不可解绑
-
class 和 struct的区别
- 默认访问级别
- class:private
- struct:public
- 默认访问级别
-
string* str,strA;
- 声明了一个指针str,和一个string对象strA
- 区别:string* str,*strA;
标准库类型
- string的cin 和 getline函数的区别
- string类型的输入操作符cin
- 忽略有效字符前面的所有空白字符
- 再次遇到空白字符,读取终止
- getline
- 不忽略有效字符前的空白字符
- 读取字符到出现换行符
- string类型的输入操作符cin
- c++中string没有java中对应的equals方法
- c++ ==等价于equals()
- for循环中的i++和++i
- 效果一样
- 效率
- 无编译器优化情况下,++i 效率比 i++ 高
- 有编译器优化情况下,效率差不多
- 如果是迭代器的话,建议用 ++iterator
- vector与iterator
- 原型:for(vector<int>::iterator iter = ivecB.begin(); iter != ivecB.end(); ++iter)
- const迭代器
- vector<int>::const_iterator iterator = ivecB.begin();
相关细节
//两行代码效果一样
for( i = 0; i < 10; i++)
for( i = 0; i< 10; ++i )
Part2、容器&STL篇
Part3、面向对象篇
继承
- 派生类不可直接访问基类的私有成员
- 默认继承
- struct默认是public
- struct D1:Base
- 公有继承,等价于public Base
- class默认是private
- Class D2: Base
- 私有继承,等价于private Base
- struct默认是public
- 友元关系不能继承,不管是友元类,还是源类
类与对象
1、class&struct
- Class:默认缺省时,成员被认为是私有
- Struct:默认所有成员都为公有
2、定义类和对象
- 在类内定义成员函数默认为内联函数
- 类可以无名,用于直接声明对象
- 可实例化常量对象
3、成员函数
- 成员函数隐含定义this指针
//该行代码会自动转为下一行代码
void setXY ( int a, int b) { x = a ; y = b ; }
//this指针不能这样显式声明,但可以显式使用
void setXY ( int a, int b, Simple * const this ) { this->x = a ; this->y = b ; }
4、拷贝构造函数
- 特殊的构造函数
- 定义:用已有同类对象对正建立的对象进行初始化
- 形式:类名 :: 类名(const 类名 & 引用名 , …);
- C++会为类提供默认版本的复制构造函数,也可以自定义
- 分类
- 浅拷贝
- 默认拷贝构造函数一般为浅拷贝
- 拷贝对象与源对象共享内存呢,易产生野指针
- 深拷贝
- 浅拷贝
5、静态类&函数&成员变量
- 类中声明静态变量后,一定要初始化
- 必须在类外初始化
- 不能在类内初始化
- 静态函数中设置非静态变量
- 须指定具体对象
- 编译器需知道该非静态变量属于哪个对象
- c++中没有静态类的说法
6、友元
-
分类
- 友元函数
- 友元类
声明友元类后,友元类可访问元类的私有成员
-
特点
- 有助于数据共享和工作效率
- 不利于数据封装与数据隐藏
-
相关代码
- 类中定义本类
运算符重载
1、通过重载运算符函数,重新定义运算符的操作
2、运算符函数
- 特殊成员函数
- 语法形式:类型 类名 :: operator op ( 参数表 )
- 实现形式
- 成员函数实现
Object . operator op () - 友元函数实现
operator op (Object) - 区别
- 传递参数的方式不同,实现代码不同,应用场合也不同
- 成:有this指针;友:无this指针
- 成员函数实现
3、继承
- 不论种方式继承基类,派生类都不能直接使用基类的私有成员
- 子类会创建父类的私有成员,但不可访问父类的私有成员,只能通过公有成员函数访问
- 实例化派生类时,先初始化基类构造函数,再是派生类构造函数
- 虚基类、虚函数、纯虚函数
- 构造函数不能是虚函数
- 析构函数可以是虚函数
- 一个具有纯虚函数的基类,成为抽象类
- 子类调用父类成员函数
- ( ( Father * ) this ) -> Print();
Part4、疑问篇
try/catch/throw异常处理
-
方式:
- 主动throw,主动写catch捕捉
- 自定义异常类来处理
- 使用标准异常处理
-
相关细节
- throw异常抛出,如果没有相应的catch捕捉,会报错
- 不管throw几个,只捕捉最先的一个异常
- 捕捉未知异常时,可用catch(...)
- c++中没有Java中的throws
异常处理流程
-
throw理解
- 函数内抛异常,上一级函数catch的话,访问的只是异常对象的副本而已
- 尽量throw对象的指针
例:throw new E(); - 在构造函数中抛异常,不要在析构函数中抛
- 使用异常的成本
- 异常没发生时
- 代码膨胀5%-10%
- 执行速度也同等下降
- 异常发生
- 执行速度比正常情况慢三个数量级
- 异常没发生时
typedef的四个用途和两个陷阱
- 用途
- 定义一种类型的别名,不只是简单宏替换
- 声明struct新对象时,必须要带上struct,使用typedef,可以省略它
- 定义数组别名
- 为函数指针定义新的名称
- 陷阱
- 注意指针
- 注意常量修饰
- 详细请查代码《c++primer》1_7.疑问汇总测试
枚举类型与int的恩怨
- 标准c中可转换
- c++标准不可以
- enum color{red, green, blue};color c = 1 ;
- c编译器可以通过,自动转换成green
野指针(悬垂指针)、智能指针
定义
维基百科说法:野指针==悬垂指针==迷途指针
-
另一说法:
野指针:声明,但未初始化的指针
悬垂指针:指针指向的空间已被释放,而指针未被NULL
智能指针:消灭(野、)悬垂指针
-
野指针防范策略
- 不用默认拷贝构造函数,自己写一个 ——值型的方式管理
- 使用智能指针——使用引用计数
- 引用计数存疑,autoptr,unique_ptr貌似木有技术概念
指针传递本质上还是值传递
引用和指针的区别
strcpy和strncpy区别
引用形参和指针形参
PART5、泛型编程
定义
- 独立于任何特定类型的方式编写代码
- 模板是泛型编程的基础
- 类是对象的抽象,模板是类的抽象
两种多态
- 运行多态,即虚函数实现的多态
- 编译时的多态,即泛型编程,体现在参数的多态
函数模板: 与重载相比
函数模板只适用于参数个数相同,而类型不同的情况