C++面向对象基础知识(二)

这个笔记主要记录一下c++面向对象中常用的Composition(复合)、Delegation(委托)、Inheritance(委托),以及三者构建的各种设计模式。

复合

template<class T>
class queue{
protected:
	deque<T> c;
}

1.上图展示的是复合,一个类中包含某一个类的对象,有些地方又称为成员变量,queue是队列,deque是双端队列,我也不知道上述复合的定义是否规范,但我感觉复合主要适合以下场景:现实中,用户想要的某个功能已经实现了,只是需要在此基础上增加某些功能或者更改接口名字,那就可以在类中包含已经实现功能类的对象,就如上图所示,queue中某些功能已经被deque实现,直接包含进来就行,queue一般被称为适配器。
2.在这种情况下一般先调用deque的构造函数,再调用queue的构造函数,构造一般是由内向外的,犹如建楼房一样,析构一般是由外向内的。
3.编译器一般调用默认的构造函数,因为构造函数可以重载,所以编译器一般自己选择默认构造函数,如果想调用别的构造函数,可以自己实现。

委托

class StringRep
class String{
private:
	StringRep* rep;
}

1.委托与组合最大的不同是:组合的生命周期是一样的,在类对象创建时类中的成员变量也创建了,委托则是在需要时才通过指针创建对象,由用户决定什么时候创建成员变量,我总感觉这种形式有点像晚绑定,也不知道对不对。
2.这样做可以调用指针类展现对外的接口,指针类完成内部实现,每次变动都只用改动指针类,又称为编译防火墙。

继承

1.继承应该都很熟悉,只要是面向对象都有继承,在继承中表示子类是父类的一种。
2.创建对象时由内向外,会先调用基类的构造函数,再调用子类的构造函数。析构时由外向内,先析构子类,再调用基类的析构函数。
3.父类的析构函数最好是虚函数。
4.数据可以被继承下来放到内存中,函数的继承则是函数的调用权。
5.一般情况下正常函数不希望被子类覆盖,虚函数有默认定义的可以被子类覆盖,纯虚函数没有默认定义的一定要被子类覆盖。
下面介绍一个经典的虚函数例子:

CDocument::OnFileOpen()
{
	...
	Serialize();
	...
}

class CMyDoc:public CDocument
{
	virtual Serialize();
}

main()
{
	CMyDoc myDoc;
	myDoc.OnFileOpen();
}

上图CDocument类表示文件打开读取的操作,对于不同文件,打开文件读取的流程是可以共用的,但是读取文件的操作不能共用,要根据文件的格式来决定,上图中Serialize函数表示读取文件的操作。因此该函数被设为虚函数,需要由子类重写,子类CMyDoc重写完后调用OnFileOpen函数,除了Serialize函数调用子类自己重写的函数,其余步骤均调用父类的接口流程,这种实现就是真正的晚绑定。
上述也被称为模板模式,把可以决定的重复步骤写好,把决定不了的步骤放到子类实现,mfc就是按照这种模式实现的。所以框架听起来很厉害,其实就是决定接口的调用流程加上提供虚函数接口。后面会介绍一种设计模式,框架也可以实现未来的类。
在上述例子中,CMyDoc类调用OnFileOpen函数,相当于把CMyDoc地址传给this指针,调用Serialize函数时,相当于this指针调用该函数,因此调用的是CMyDoc类中的Serialize函数。

Composite组合设计模式

今天太晚了,图等到周末再补。。。
如果有一种情况,某一种组合中不仅能放单个对象也能放组合,犹如积木一样,地理科学研究中有一个方向叫集成建模框架,每一个模块代表陆面过程模型的一个物理子过程,使用时通过各种组合模块:顺序执行模块、条件执行模块等将这些物理子过程组合起成新模型,组合模块不仅能存放单个物理子过程也能存放其他组合模块,那遇到以上情况该怎么设计呢?
组合设计模式就是一个很好的解决方案,组合设计一个类Composite,单个对象也是一个类Primitive,这两个类都继承于同一个基类Component,组合中vector就存放的是Component,同时Component中有add虚函数接口可以被Composite集成往vector中添加Component,但在该情况下add接口不能设为纯虚函数,因为Primitive不需要添加这个功能。

Prototype原型设计模式

同样图到周末补。。。
如果一个框架,类在几十年之后再设计,框架不知道之后类的名字,如何通过框架来创建之后的类对象。这种设计模式给人一种注册服务的感觉,之后的类在框架中注册一下,框架就可以创建类对象了,也不知道直觉对不对。
那么上述情况,设计框架为基类,基类中有addPrototype接口负责将类注册进来,有一个列表存储基类指针,findAndClone接口负责循环列表创建子类对象,clone虚函数接口由子类重写来创建对象。
未来的类为子类,子类中设计有类的静态对象,构造函数中调用基类addPrototype接口将子类加入到基类的列表中,静态对象在使用时必须要定义,这样在静态对象定义时就能直接将子类注册到基类的列表中。
基类中提供clone虚函数接口,子类通过继承重写该函数来实现对象的创建,但重写的clone中不能调用之前的构造函数,因为之前的构造函数提供注册的功能,一个类只能注册一次,所以最好的办法就是重载构造函数,在构造函数多加一个参数就行。
以上就实现了原型设计模式,子类通过静态类成员变量不得不定义的特点实现类的注册,然后基类通过遍历列表,findAndClone接口中调用每个基类指针的clone接口实现对象的创建。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值