题外话:侯捷老师难得一年就来上九堂课就要会宝岛,特此留念签名赠语及合照以自勉。

 学海无涯,为勤是岸

<正文开始>

  昨天晚上连上了3个小时的大课探究单单讲了Adapter一个类,幸运的是本人恰好在大一的时候接触过比如<functioinal>库类中的bind1st,bind2nd这些函数对象的使用方法,毕竟若要使用<algorithm>的话,里面几乎每一个函数都需要我们把模版中的函数对象比如Comparato之类的重写一下,但是真的没有想到,这些库这些类使用起来明明那么简单但是在老师的讲解下里面的结构和设计人员的思路原来真的是复杂缜密。

  具体说Adapter(适配器)这种设计之前必须要先简单说说LSP(里氏替换原则),其内容是:子类(derived typed)必须能够替换掉它的基类(base type)。这一句话就有点让我摸不着头脑了,既然是子类已经从基类继承过来了,那岂不就是子类必然能够替换掉父类么?不然多态(polyporphism)还从和谈起?如果是在java里的话,(我觉得)也许这点是毫无争议的因为java有强大的继承体系一切类都要从Object类继承而来(lambda表达式的目标对象也不是一种类,所以不算从Object继承而来),然而在C++语言之中另有一种独特的设计--private继承,这种独特的继承方式会是父类中无论是protected还是public继承抑或是多重继承过来的指针引用都转变为子类的private数据,也就是说这些数据在继承树的这条分支上已经被宣告了终结。所以象在MFC这样的库的建立的时候LSP原则是必须遵守的,不然会给程序带来(严重的)隐患。

课件中所示,Adapter设计一般有三种(昨天只讲了两种):

(1)Container Adapter

  这个库的底层容器我们可以看到选择的是deque,值得注意的是在这套设计之中queue和deque是复合的关系,但是和我猜测的相反,queue包含了deque类也就是说queue是在deque之上架构起来的,至于为什么明明deque和(双驱)list有相同的“效果”甚至有相同的方法命名却选择了deque来作为默认的底层容器,老师谦虚地讲他也不敢下定论,但是我们至少可以大胆地推测deque的速度或者效率是优于list的。而且在这里面queue“HAS-A”deque这样的关系,在这个结构之中架构起来的更多的容器基本上都是以底层容器出发,改写方法添加约束从而完成架构。在《More Effective C++》中的编程准则之中有提到过,建议编程者将一切的数据写入private之中,但是这并不意味着这个类在继承链上部分数据的残缺,因为我们会在public或者protected中声明它们的getter&setter(是否想起了java呢:-P)来不断地继承过来对这个数据的操作权从而实现安全架构。

##stack容器的实现和queue的实现是极其相似的,这里不多赘述##

(2)Function Adapter

  这部分较上部分较难懂的,例子中的Adapter简单的来讲就是要实现一个功能:参数绑定。有的函数对象作为参数可能只需要一个参数来进行调用,但是我们这里却只用一个双参的函数对象无法直接使用作为参数,那么最效率的解决方法就是使用Adapter。当然不要自信地认为会用了这个binder系列not系列函数就是理解了Adapter,深入了解架构,才能帮助我们写出自己想要的Adapter,了解STL的规范才可以帮助我们写出的Adapter更好地与上层容器/上层对象相兼容。比如要写出一个三参绑为一个四参绑为两个这些特殊的情况才会有良好的方案去解决。

  例子是假设我们要使用count_if函数,这个函数在<algorithm>库中的作用是if xx then count计数,其中的第一个参数和第二个参数当然是Iterator类型,然而第三个参数我们需要一个单参的Predicate函数对象或者函数指针。如下图所示,其实在这里面Predicate只是template中的一个命名,它可以是T,Fxxx各种名字,但是一个Predicate的名字就可以让其他人看出这个函数对象最后需要返回的是一个布尔值,如果一旦模版实例化为一个将操作符重载为例如void operator()(Paramlist..)这样的函数时,那么在count_if内部的判断分支语言就会遇到麻烦,而且由于c++的灵活性如果将返回值重载为int /long类的话,这样count_if就不会报错程序照常执行的同时,会给貌似正确程序埋下隐患。

  那么Adapter是怎么样架构起来的呢?下面这张图很好地概括了下来。如下图所示(其实那个f和x之间按理来说应该有个逗号Anyway~)Adapter的实现过程就是在构造的时候将需要绑定的参数绑定下来,然后重载操作符使之成为一个新的函数对象。是的,貌似非常简单,但是接着向下看,如果考虑到functionAdapter是从unary_function和binary_function继承而来的模版结构的话,会大大增加复杂度,整个搭建起来adapter的过程也是不断地向父类“询问”typedef类型的过程,这些约束是adapter中最难理解的部分。

 最后我们再来看一下具体的实现宏观过程:

##课后提问##

我:在C++11的新特性中已经允许了自动类型推断,而为什么黑板上强调的bind2nd的模版类型必须和参数类型表明一致?:::(黑板)bind2nd<less<int>>(less<int>(),12)

侯捷:因为C++11的自动类型推断只能运用在模版函数之中,但是对于模板函数对象,我们必须前后表明参数和函数对象的模版。

<软件架构与设计模式>侯捷老师关于Adapter类在STL中的深入解析和模式探讨的更多相关文章

  1. Adapter类 调用Activity中的函数

    在Adapter类中可以定义一个MainActivity变量,在初始化时,对其赋值,例如fragment的适配器中: private MainActivity context; private Lis ...

  2. 侯捷老师C++大系之C++面向对象开发:(一)不带指针的类:Complex复数类的实现过程

    一.笔记1.C++编程简介 2.头文件与类的声明 防卫式声明#ifndef __COMPLEX__#define __COMPLEX__ …… #endif头文件的布局模板简介template< ...

  3. vector源码3(参考STL源码--侯捷):pop_back、erase、clear、insert

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷):空间分配.push_back vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 v ...

  4. vector源码(参考STL源码--侯捷):空间分配导致迭代器失效

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...

  5. vector源码2(参考STL源码--侯捷):空间分配、push_back

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...

  6. vector源码1(参考STL源码--侯捷):源码

    vector源码1(参考STL源码--侯捷) vector源码2(参考STL源码--侯捷) vector源码(参考STL源码--侯捷)-----空间分配导致迭代器失效 vector源码3(参考STL源 ...

  7. 侯捷《C++面向对象开发》——动手实现自己的复数类

    前言 最近在看侯捷的一套课程<C++面向对象开发>,刚看完第一节introduction之后就被疯狂圈粉.感觉侯捷所提及所重视的部分也正是我一知半解的知识盲区,我之前也写过一些C++面向对 ...

  8. 侯捷STL学习(一)

    开始跟着<STL源码剖析>的作者侯捷真人视频,学习STL,了解STL背后的真实故事! 视频链接:侯捷STL 还有很大其他视频需要的留言 第一节:STL版本和重要资源 STL和标准库的区别 ...

  9. 侯捷STL课程及源码剖析学习3: 深度探索容器list

    一.容器概览 上图为 GI STL 2.9的各种容器.图中以内缩方式来表达基层与衍生层的关系.所谓的衍生,并非继承(inheritance)关系,而是内含(containment)关系.例如 heap ...

随机推荐

  1. .NET CORE 2.0小白笔记(二):VS插件 ReSharper Ultimate 2017 安装破解

    采用Use License Server方式激活,如果有多台要激活的可以用一个当服务器 下载网盘:链接: https://pan.baidu.com/s/1nvacvKP 密码: ipxc 版本:Je ...

  2. IntelliJ IDEA 、genymotion模拟器、Android开发环境搭建

    首先打开IDEA,看到该界面,如果没有该界面,请在User/用户名/IntelliJIDEAProjects/下删除所有项目文件夹.然后重启IDEA即可看到 接着开始配置jdk和sdk 然后在Proj ...

  3. 使用rsa进行http传输加密

    目录 1. RSA算法 2. HTTPS 2.1 HTTPS优点 2.2 HTTPS缺点 3. RSA传输加密实现 3.1 所需插件 3.1.1 JS插件 3.1.2 所需JAR 3.1.3 代码 4 ...

  4. EasyUI datagrid border处理,加边框,去边框,都能够

    以下是EasyUI 官网上处理datagrid border的demo: 主要是这句: $('#dg').datagrid('getPanel').removeClass('lines-both li ...

  5. python的list求和与求积

    python中,无论是对的list求和还是求积,我都给出了两种方法. 1.对list求和 1.1 s=0 for i in range(10): s+=i 1.2 s=sum(range(10)) 2 ...

  6. CSU 1663: Tree(树链剖分)

    1663: Tree Time Limit: 5 Sec  Memory Limit: 128 MB Submit: 26  Solved: 11 [Submit][id=1663"> ...

  7. 算不算类似微信小程序

    这几天微信发布的微信里生成小程序,刷爆了朋友圈. 微信生成的小程序不用下载安装就能在手机里出现,即用即删. 想到这里,我想到苹果手机本身再带类似于微信的小程序的呈现方式,也可以即用即删,那是我在去年久 ...

  8. Lumen开发:phpunit单元测试

    先来直接运行,cmd先进入根目录,然后进入tests或是test文件夹 运行命令行:..\vendor\bin\phpunit ExampleTest.php laravel/lumen中集成了PHP ...

  9. Residual (numerical analysis)

    In many cases, the smallness of the residual means that the approximation is close to the solution, ...

  10. Modeling of Indoor Positioning Systems Based on Location Fingerprinting

    Kamol Kaemarungsi and Prashant Krishnamurthy Telecommunications Program School of Information Scienc ...