侯捷C++面向对象高级编程(上)笔记
文章目录
1. 构造函数:
函数若在class body内定义完成,便为inline函数(内联函数)
inline函数速度更快
也可以在内声明外用inline建议编译器设置为inline函数,但当函数复杂时是不会被设置为inline的(编译器没有能力)
类内赋值大气的写法是用初值列(初始列),大气且效率高.在大括号内就是赋值的写法了,两阶段:初始化,赋值…所以效率上用初始列效率高
- 构造函数可以放在private中,很著名的写法就是单例模式(singleton)
- 常量成员函数(函数后头加const):意思即是不改变里面数据的内容;并且有时候必须要加const,很多人会忽略
- pass by value 和 pass by reference , 传递引用只需传递一个指针,所以传引用速度很快(传递一个指针的速度),但是值传递是多少byte就要传递多少byte. 所以尽可能都传引用. 希望不改的话可以pass by reference to const
- 还有返回值的传递,和参数传递一样尽量传引用(如果可以的话,可能也会有特殊情况: 比如生命周期问题, 是local(局部)的就一定不能传引用)
- friend友元: 可以自由获得friend的private成员; 相同class的各个objects互为friends(友元)
- 综上,设计一个类大气方式:1. 数据放private 2. 参数尽可能用reference来传 3. 返回值也尽可能用reference来传 4. 类的本体body里应该加const就加 5. 构造函数尽量用初值列(初始列)
2. 操作符重载 (作用在左边身上)
- 所有成员函数带有隐藏参数this指针
- operator overloading操作符重载1,成员函数 this
- 作符重载2,非成员函数 无this 临时对象:typename(),比如类complex,可以些临时变量complex(1,2)…
3. 关于拷贝、new和delete
class without pointer member(s): 典型:complex
class with pointer member(s): 典型:string; 此时不能用编译器自带的拷贝构造拷贝赋值,因为这样会引起浅拷贝(类内自带指针,如string类的数据其实是一个指针指向字符串),所以必须自己重新写拷贝构造和拷贝赋值
- stack heap
- 调用函数时函数本身即会形成一个stack;而若类内是static object, 其生命在作用域结束之后仍然存在,直到整个程序结束
- 函数作用域之外的即是global object,其作用域是整个程序
- new完要delete防止内存泄漏
- new:先分配memory,再调用ctor; 一共三步:分配内存、类型转换、构造函数
- delete:先调用dtor,再释放memory; 一共两步:析构函数、释放内存
- malloc:上下加固体块表示长度(以后销毁的时候告诉编译器销毁大小)。灰色是调试模式下的情况
- ctor和dtor(构造函数和析构函数)
array new搭配array delete,否则会造成内存泄漏
4. 单例模式等简单介绍
类的函数处理对象,非static函数,靠的是this指针来传递,然后才能靠this指针来找数据(成员函数默认带this指针)
static数据只有一份,独立于object。必须要在类外去定义(初始化),类内则只是声明,至于要不要给初值都可以。
静态(static)函数则没有this pointer。于是静态函数只能处理静态数据。
著名写法(单例模式):
我们不想让任何人去构造A类了,只存在一个就行了。把构造函数放在private里头。对外提供一个getInstance接口。这是一种设计模式。
把构造函数放private里,这样外界就不能再次声明了。
而把static的构造放在接口的函数里,而不放private里,好处是:放private里也能起到作用,但是要是外界没人使用这个类,就浪费了一次空间。放在接口的函数里,当外界使用第一次的时候就构造了。是非常好的一个写法。
进一步补充,类模板:
事实上尖括号就是告诉编译器,比如<double>,编译器看到之后就会把T全部变成double,所以可能造成代码膨胀,但这是必要的。
进一步补充:函数模板
进一步补充:namespace
可以自己去把一段代码包装在namespace里
如著名的std就是:
namespace std
{
…
}
而全部打开则是using namespace std;当然也可以一个一个打开or写全名(using std::cout 或 std::cout)。
5. oop , ood (object oriented programming, object oriented design)
1. composition(复合),表示has-a
- Adapter构造模式:改造一下(如queue与deque,deque强大,queue使用了deque只提供个别接口就成了queue)
- composition下的构造析构(编译器会自动帮忙,比如下图红色部分,当然参数是default的,如果不要是default的就得自己写):
2. Delegation(委托). composition by reference (学术界不讲by pointer只讲by reference,哪怕是指针)
下图:非常有名的写法。编译防火墙,一个类用指针指向另一个类,功能在那里实现。这样比如abc三个对象可以共享一段空间,但是当a要改的时候我们可以单独复制一块新的给a来改动,bc则保持共享
3. Inheritance(继承),表示is-a
三种关系都是面向对象的一部分
有public有private有protect继承,最常用的就是public,而如Java就只有public继承,所以Java不用特别写出来public
继承和虚函数搭配最有价值
和composition一样,构造由内而外(先打造根基),析构由外而内(层层拆封),继承则是子类里包了父类的part
base dtor(父类的析构函数)必须设置为virtual
虚函数与多态
23个设计模式之一:Template Method
把固定的框架先写好,留下的重要的部分构造为虚函数留待以后写
Composite:
Prototype:(希望创建未来要用到的子类)