C++笔记三(面向对象编程上)

十一 组合和继承

OOD(Object Oriented Design)
(1)基于对象:单一类的写法;
(2)面向对象:类与类之间的关系,包含三种:Composition(复合)、Delegation(委托)、 Inheritance(继承)。

11.1 Composition表示has-a

14.png

如上图所示,queue类中有deque类,称为queue has-a deque即类的复合。
这也是一种设计模式Adapter,queue类拥有deque类,而且queue所有的函数功能都借用deque类来实现。deque功能非常全,queue根据用户开放部分的功能,queue是一种adapter。


15.png

这是复合在内存中的表现,queue类有deque类,deque类有Itr类,sizeof的计算如图所示:


16.png

类之间在复合关系下构造函数与析构函数的顺序为:
(1)构造由内而外。container的构造函数首先调用Component的default构造函数,然后才执行自己。
Container::Container(...):Component(  ){ ... };

(2) 析构由外而内。container的析构函数首先执行自己,然后才调用component的析构函数。

Container::~Container(...){ ... ~Component(  ) };

11.2 Delegation(委托) (Composition by reference)

17.png

(1)如图所示左边有指向右边的指针,这种叫委托。它和复合的区别是复合内外部是一起出现,两者生命周期同步;而委托则是允许外部先创建出来,等需要的时候再把内部写好,两者生命周期不同步。
(2) 图示写法叫做Handle/Body或者pointer implementation(pimpl)。左边是对外的接口,右边是功能的实现,右边不影响左边,右边可以更改甚至指向别的类,具有良好的弹性。

11.3 Inheritance(继承)表示is-a

18.png

子类从父类继承了数据和函数(函数继承的是调用权)。


19.png

类之间在继承关系下构造函数与析构函数的顺序为:
(1)构造由内而外。Derived的构造函数首先调用Base的default构造函数,然后才执行自己。

Derived::Derived(...):Base(  ){ ... };

(2) 析构由外而内。Derived的析构函数首先执行自己,然后才调用Base的析构函数。Base class的析构必须是virtual,否则会出现undefined behavior!

Derived::~Derived(...){ ... ~Base(  ) };

十二 虚函数与多态

12.1 虚函数及其应用

继承最有价值的是和虚函数的搭配使用。成员函数从虚函数的角度出发分为三种:
(1)non-virtual函数:你不希望derived class重新定义(override,重写)它;
(2)virtual函数:你希望derived class重新定义(override,重写)它,且你对它已有默认定义;
(3)pure virtual函数:你希望derived class一定要重新定义(override,重写)它,且你对它没有默认定义。

虚函数应用实例如下:


20.png

旧文件的开启与读取,check file name 、search file 、open file任何人写的都差不多,可以事先写,但是因为每个人读取的文件类型不一样,所以读取这个动作不能事先写。框架如下:


21.png

应用框架CDocument中已经事先写好check file name 、search file等函数,CMyDoc是CDocument的子类,没法事先写的Serialize()设计为虚函数(可能为空函数,也可能为纯虚函数),使用流程如图箭头所示,创建一个子类的对象,通过子类的对象调用父类的函数,遇到Serialize()时父类函数去找子类的定义,然后再将剩余的动作完成,将Serialize()延缓到子类去定义,这种用法就叫做Template Method(23种设计模式之一,Method是java中的函数)。
这种设计模式适合做框架,MFC大量用到Template Method。

具体代码实现(仿真):


22.png

12.2 继承+复合关系下的构造与析构

23.png

在图示继承+复合关系下构造函数与析构函数的顺序为:
(1)构造由内而外。Derived的构造函数首先调用Base的default构造函数,然后调用Component的构造函数,最后才执行自己。

Derived::Derived(...):Base(  ),Component(){ ... };

(2) 析构由外而内。Derived的析构函数首先执行自己,然后调用Component的析构函数,最后调用Base的析构函数。

Derived::~Derived(...){ ... ~Component(),~Base(  ) };
24.png

在图示继承+复合关系下构造函数与析构函数的顺序为:
(1)构造由内而外。Derived的构造函数首先调用Component的default构造函数,然后调用Base的构造函数,最后才执行自己。

Derived::Derived(...):Component(),Base(  ){ ... };

(2) 析构由外而内。Derived的析构函数首先执行自己,然后调用Base的析构函数,最后调用Component的的析构函数。

Derived::~Derived(...){ ... ~Base(  ) ,~Component()};

12.3 多态实例

功能最强大的是委托+继承设计方式。
委托+继承设计实例1(Observer):


25.png

左边为放数据的class,右边为观察的class,左边可以有很多的右边,左边数据装有指向右边指针的容器,右边可以被继承,将来创建的子类is a Observer都可以放在容器里面,所以可以产生不同的Observer。
左边要提供注册和注销的功能,如图attach传入Observer放到容器里头。左边还应该有notify把所有Observer进行遍历,去通知Observer,内容由Observer写好,左边调用。


26.png

如图所示有多个窗口看同一份文件或者不同角度看同一份数据。实现代码如下:
27.png

委托+继承设计实例2(Composite):
28.png

文件系统:Primitive代表文件,Composite是一个容器,容纳很多个Primitive和Composite,所以设计一个父类Component,Primitive和Composite都is a Component,Component和Composite是委托的关系。add函数和容器类似,add不能设计为纯虚函数,因为Primitive不能定义。

委托+继承设计实例3(Prototype):
我需要一个树状继承体系,子类未来才被派生,不知道未来子类的名称。让派生的子类创建一个自己当成原型Prototype,让我有办法去看到子类创建出来的的原型放在什么位置上。


29.png

在LandSatImage类里面放一个静态的对象LAST,他的类型是LandSatImage(自己),构造函数写成私有的,通过私有的构造函数调用addPrototype,将自己挂上去,addPrototype是父类写的,它将得到的指针放到容器里头去,这样就可以使破折号下面创建的原型放到上面去,可以被上面看到。子类准备一个函数clone,它new一个自己。破折号以上可以通过原型(这是一个对象)可以调用clone这个函数,做出一个副本,如果没有原型则不能。
clone不能是静态函数,因为静态函数的调用需要class name,这里没有。
实现代码如下:


30.png

31.png

32.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容