侯捷C++面向对象高级编程笔记
侯捷C++面向对象高级编程笔记
1.传值vs传引用
尽量传引用以及返回引用。
1.1函数返回引用
返回local object(局部物体)时,不能返回引用,如下图:
所以反向分析函数体中的return:当你看到一个函数返回是引用类型时,不用慌张,看&前的类型即可正确写出return啥。
1.2传引用形参
速度快,因为无需复制整个实参进来,注意点:考虑是不是要改变实参的值,若不能加个const限定。并且,数组形参只能传指针。例如:
1.3 其他细节
1.3.1 temp object
生命周期只有该行,甚至没有名字。如上图的标黄部分。
1.3.2 const
c++函数前面和后面使用const的作用:
- 前面使用const,const修饰函数返回值,也是用const来修饰返回的指针或引用,保护指针指向的内容或引用的内容不被修改,也常用于运算符重载。归根究底就是使得函数调用表达式不能作为左值。
- 后面加const表示函数不可以修改class的成员
1.3.3 操作符重载
注意返回值最好是支持连着调用的。例如c3+=c2+=c1;
以及cout << c1 << conj(c1);
所以重载函数的返回类型大有文章!
cout << c1 << conj(c1);
的分析:其实分为两步,先cout << c1;
2.含指针对象的类
2.1总述
必须手写拷贝赋值和拷贝构造函数,否则会造成内存泄露!
附:在C语言函数中:
原型声明:char *strcpy(char* dest, const char *src);
头文件:#include <string.h> 和 #include <stdio.h>
功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
那么,如何判断是拷贝构造函数被调用还是拷贝赋值函数被调用?
蓝色的那两行是一样的,都是调用拷贝构造函数。结论(判断依据):当新对象被定义,则一定有个拷贝构造函数被调用。
【注】此图还有个细节:相同class的各个objects互为friends(友元)。所以可以直接访问另一个object的private data。
2.2拷贝赋值函数
实现逻辑:1.将自身指针delete;
2.申请和右值一样大的空间
3.strcpy
但是,注意要检测自我赋值:
2.3其他细节
array new没搭配array delete可能会造成内存泄漏,例如带指针成员的string类。而不含指针成员的不会泄露。
3.补充
3.1static
3.1.1static 成员函数
- 没有this指针,所以不像通常成员函数那样处理普通成员变量。
- 要在class外写定义式
3.2模板
3.2.1类模板
使用时需明确指出类型。template<typename T>
3.2.2函数模板
和类模板不同,函数模板的参数可以实参推导。
3.类之间的关系
3.1复合
实心菱形表示
3.2委托
空心菱形表示
3.3继承
空心三角形表示
4.委托相关的设计模式
4.1Delegation (委託) + Inheritance (繼承)
4.1.1比如同一份文档,有多个人观察
4.1.2比如文件系统,既可包含最原始的(primitive)文件,也可以包含自身(文件夹)
注:因为文件系统要既可包含最原始的(primitive)文件,又可以包含自身(文件夹),所以add方法的参数要父类!
4.1.3 创建未来类的一种方法
这里的思路就是在未来类中添加一个静态变量,然后将构造函数变为私有方法,里面写上addPrototype()函数。说明:下划线表示静态成员。
上图有个细节:由于LandSatImage::clone()
中new了一个LandSatImage,所以会调用它的构造函数,但我们不能让他这么做,否则addPrototype()再次调用。所以写了个protected的构造函数,它接收一个int类型的参数,以此与private的构造函数区分!
对该程序的分析:因为LandSatImage和SpotImage类都分别有静态变量_landSatImage和_spotImage且都必须在类外声明。所以已经调用了两次他们父类的构造函数,所以图中的_nextSlot的值为2.