一、虚函数
1.语法
在任何一个成员函数之前加上virtual
子类可以调用父类的函数,继承的是调用权
2.分类
(1)非虚函数(non-virtual):你不希望子类重新定义(override,复写)它。
(2)虚函数(virtual):你希望子类重新定义它,且它已有默认定义。
(3)纯虚函数(pure virtual):你希望子类一定要重新定义它,你对他没有默认定义。
3.对shape类的想法:
1.shape是一个很抽象的概念,是形状,接着三角形,正方形可以继承shape类
2.objectID为非虚函数
3. error 为 虚函数,操作失败,可以丢出一个错误代码,例如显示:(三角形/正方形)设计错误!
子类可以重新定义这段代码
哪一种形状出错,自然可以调用哪一种形状的error函数
4.draw 为 纯虚函数,一定要被所有子类重新定义。
因为父类是shape,根本不知道怎么定义。
打开菜单,弹出对话框,输入或选择文件名,程序收到文件名并检查文件名是否合理,查找文件,打开文件,打开之后读出来,只有读取的内容是不同的,其他的操作都可以事先写好,让后面的人用。
类中的成员函数都是以this为调用的,所以this->Serialize()在以CMyDoc的对象调用以后,传入的是myDoc的地址,最后调用了其函数,实现了具体实现
Template Method就是一种写好一个框架把可以设定的都设定好,然后再实现过程中以虚函数的方式让具体实现交由继承它的类,完成各种不同的功能。
灰色的线表示函数的执行过程。
二、继承+复合下的构造和析构函数
1.子类里有父类的成分,又有component
当你创建子类时,构造函数应该先调用父类,再调用component,最后是子类
析构函数相反
2.子类有父类的成分,父类中有component的成分,
构造函数次序:component,base,derived
析构函数相反
三、委托+继承
栗子:
对于同一份文件,有多种view,存储文件和表现文件这两个class呈现怎样的关联呢?
subject (存放数据)
observer(观察数据)
目的:让subject可以拥有很多个observer
准备一个向量容器存放指针,指向observer,而observer作为一个父类,可以派生出很多子类,子类都是一种observer,子类都可以放入容器中
class subject{
private:
int m_value;
vector<observer*> m_views;//一个容器包含多个窗口,就可以实现多个窗口
public:
void attch(observer* obs){
m_views.push_back(obs);//谁要使用就来注册,开辟窗口,放到容器里
}
void set_value(const 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(suject& sub,int value);//一个父类,让每个子类窗口的表现都可以不一样
};