本文用来复习在侯捷中的OOP部分

OOP的核心思想是数据抽象继承动态绑定

侯捷笔记:

堆,栈,内存管理

Stack。是存在于某作用域(scope)的一块内存空间(memory space)。例如当你调用函数,函数本身即会形成一个stack用来放置它所接收的参数,以及返回地址。在函数本体(function body)内声明的任何变量,其所使用的内存快都来自于上述的stack。

Heap。也叫system heap,是指由OS提供的一块global的内存空间,程序可动态分配从中获取若干区块(blocks)

class Complex{...};
...
{
Complex c1(1,2); // 创建的空间来自stack
Complex *p = new Complex(3); // 创建的空间来自临时的Heap,需要释放
}

其中,c1就是所谓的stack object,生命会在作用域(scope)结束后自动被析构函数清理。又叫座auto object

如果加上static,就是一个静态对象,在作用域结束之后不会被清理,直到程序结束。

写在作用域之外,叫做global object,可以看做是static,作用域是全部。

class Complex{...};
...
{
Complex* p = new Complex; // 这是一个heap object 在delete之后生命结束
...
delete p;
}

如果不delete,就会发生内存泄漏,因为当作用域结束后,p指向的heap object并没有被清理,但是指针p的生命结束了,作用域之外看不到p,也没有机会再清理p的空间了。

new:先分配memory,再调用ctor

Complex *pc = new Complex(1,2);
//上面的代码可以进行拆解
void* mem = operater new(sizeof(Complex)); // 分配内存 operater new 内部调用的是maclloc sizeof 8
pc = static_cast<Complex*> (mem); // 数据进行转型
pc->Complex::Complex(1,2); // 构造函数 this指针

delete:先调用dtor,再释放memory

delete ps;
// 拆解为两步
String :: ~String(ps); // 析构函数 对于内部有动态的,得现在dtor中将空间释放
operator delete(ps); // 释放内存,内部调用free(ps) 再删去指针

动态分配所得的内存块多大array,in VC

调试模式

对于一次分配,得到32字节 和 4字节(上下),还有cookie(两块,2 * 4),共有8 + 32 + 4 + 8= 52, 但是一个block的大小是16的倍数,剩下的地方进行padding。

非调试,只要,cookie和原始对象的大小。

cookie的作用:记录整块的大小。

array new 一定要搭配array delete

static

加上static的数据(函数)就会与对象脱离联系,只会有一份属于类。

使用场景:例如银行利率,一般设计为static

静态函数没有this指针,所以不能访问,用来处理静态的数据。

class Account{
public:
static double m_rate;
static void set_rate(const double& x){m_rate = x;}
};
double Account::m_rate = 8.0; //叫做定义 可以不赋初始值
int main(){
Account::set_rate(5.0); //通过类名
Account a;
a.set_rate(5.0); //通过定义,静态函数不含有this指针。
}

单例模式:

// lazy模式
class A{
public:
static A& getInstance(){return a;}
setup(){...}
private:
A();
A(const A& rhs);
static A a;
}
//
class A{
public:
static A& getInstance();
setup(){...}
private:
A();
A(const A& rhs);
}
A& A::getInstance(){ //调用的时候才会出现,没有使用不会出现
static A a;
return a;
}

cout

Ostream 的一堆重载

模版

template<typename T>
class complex{
public:
complex (T r = 0,T i = 0):re(r),im(i){}
complex& operater += (const complex&);
T real () const{return re;}
T imag () const{return im;}
private:
T re,im;
friend complex& __dpaly(comlex*, const comlex&);
}

{
complex<double> c1(2.5,1.5);
complex<int> c2(2,6);
}

函数模版

template <class T>
inline
const T& min(const T& a,const T& b){ //编译器进行参数推导
return b < a ? b : a;
}
//这里要对
class stone{
public:
stone(int w,int h,int we) : _w(w) , _h(h) ,_weight(we){}
bool operater< (const stone& rhs) const
{return _weight < rhs._weight;}
private:
int _w,_h,_weight;
}

namespace

namespace std
{

}
//using directive
using namespace std;
//using declaration
using std::cout; // cout 不用写

其他细节

operater type() const

Explicit complex(…)

Composition(复合)

这是一个很简单的概念,表示has a,在某一个class中包含了另一个class,并且包含的这个class基本完成了所有的功能,例如在queue中包含deque。这就是adapter。也就是装饰器。

复合关系下的构造与析构

Container的构造函数首先调用Component的默认构造函数然后再执行自己的(由内向外)编译器帮助自己。

Container先调用自己的析构函数,再调用Component的析构函数。

Delegation(委托【Composition by reference】)

某一个类包含了另一个类的一个指针。寿命不一致。pimpl pointer to implentation Handle。copy on write,功能完全在另一块实现。

Inheritance继承

表示is a。父类的的数据是被完整继承下来的。

继承关系下的构造与析构

首先调用Base的默认构造函数,再调用自己的构造函数。

首先析构自己的,再析构父类的。base的析构函数必须是vitural的。

可以归纳出C++中子类继承父类时构造函数的写法的规律:当父类有显式地声明了构造函数时,子类最低限度的实现父类中的一个;当父类没有声明构造函数时,子类可以不声明构造函数或者任意地书写构造函数。

虚函数

加个vitural。函数继承的是调用权,子类函数是否需要被重新定义。

non-virtual:你不希望子类重新定义(overide)。

virutual函数:你希望子类重新定义,且它已经有默认定义。

纯虚函数:你希望子类重新定义,你对他没有默认定义。子类一定要有定义去override。

class Shape{
public:
virtual void draw() const = 0; // 纯虚函数
virtual void error(const std::string& msg); // 非纯虚函数
int objectID() const; // 非虚函数
}
class Rectangle: public Shape{...};
class Ellipse: public Shape{...};

通过子类的对象调用父类的函数。虚函数载UML图中用斜体表示,这就是Template Method设计模式。

Component+继承

委托+继承:(观察者模式 Observer)

class Subject{
int m_value;
vector<Observer*> m_views;
public:
void attach(Observer* obs){
m_views.push_back(obs);
}
void set_val(int value){
m_value = value;
notify();
}
void notify(){
for(int i = 0;i < m_views.size();++i){
m_views[i]->update(this,m_value);
}
}
}

class Observer{
public:
virtual void update(Subject* sub,int value)
}