C++【侯捷】——— 继承和虚函数
虚函数
函数的继承,继承的是调用权。成员函数分成三类:
1、非虚函数:不希望子类deriverd class重新定义override他,
2、virtual函数:希望派生类重新定义,且已经有个默认定义
3、纯虚函数:没有定义,希望子类一定要重新定义
父类是写公共的功能,不能确定的功能用虚函数来实现。
空函数和纯虚函数不一样,空函数在子类中可以不用重新写,但是纯虚函数必须得重新定义。
使用方法:
创建一个子类对象,通过子类对象调用父类函数,执行到虚函数的时候调用到子类中虚函数的实现。
这种使用方法,父类中将某个动作延缓到子类后面去自己实现,这种方法就是设计模式中的template method。很适合作框架设计,开始的时候将框架定好,也就是一般性的动作。先把固定的可以写的写好,留下的是虚函数,让子类来实现。MFC就是用这种方法。
例子:
CDocument::OnFileOpen()
{
...
Serialize()
...
}
class CMyDoc : public CDocument
{
virtual Serialize() { ... };
};
main()
{
CMyDoc myDoc;
...
myDoc.OnFileOpen();
}
myDoc.OnFileOpen();
在编译器中会转换成:
CDocument::OnFileOpen(myDoc);
调用者会变成this pointer,地址变成隐藏的参数传进去。OnFileOpen中调用其他函数时,是通过this来调用的,Serialize函数也就变成了:
this->Serialize();this就是上面的myDoc指针。
继承+复合的构造和析构
两种形式的:
1、当一个继承自父类,同时子类复合了一个类:
构造函数的顺序是父类、复合类、子类,析构函数的顺序相反。
2、一个类继承自父类,父雷的对象中有一个复合:
是三层包含关系,构造是先复合,再父类,再子类。析构是反的。
观察者模式
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_iews[i]->update(this, m_value);
}
};
class Observer //这个是个父类,可以派生多个多个观察者
{
public:
virtual void update(Subject* sub, int value) = 0;
};
Subject用来放数据,作为内容物,要提供注册attach(attach的是Observer对象)、注销dettach(上面没有写)、遍历通知notify。Observer 是个父类,可以派生多个多个观察者