//---------------------------15/04/25----------------------------

//#41   了解隐式接口和编译期多态

{

//  1:面向对象编程总是以显示接口和运行期多态解决问题:

void doProcessing(Widget& w)

{

&& w != someNastyWidget)

{

Widget temp(w);

temp.normalize();

temp.swap(w);

}

}

/*      1>w的类型被声明为Widget,所以w必须支持Widget接口,我们可以从源码中找出这个接口,看看

时什么样子的,这种接口称之为显式接口。

2>对于virtual函数,w将在运行期表现出多态。

2:Template的世界与面向对象不同,隐式接口和编译期多态变得很重要:                   */

template<typname T>

void doProcessing(T& w)

{

&& w != someNastyWidget)

{

T temp(w);

temp.normalize();

temp.swap(w);

}

}

/*      1>w必须支持哪一种接口是由执行于w身上的操作来决定的,比如上面看起来w必须支持size,

normalize,swap,copy构造函数,不等于比较等接口。这些便是隐式接口。

2>凡是涉及w的任何函数调用,有可能造成template具现化行为,这样的行为发生在编译期。

”以不同的template参数具现化function template“
会导致调用不同的函数,这就是编译

期多态。

3:再探隐式接口:

1>T并不需要提供一个名为size的成员函数,因为T有可能从base class继承而得。

2>T并不需要支持operator!=,因为有可能有个operator!=函数,接受类型为X的对象和类型

为Y的对象,而T可以被转换为X,someNastyWidget可以被转换为Y。

*/

}

//#42   了解typename的双重意义

{

/*  1:在声明template的时候,class和typename完全一样。

template<class T> 等价于 template<typename T>

2:当需要用到T中的类型时,需要明确指定是一个类型,也就是在前面加上一个typename:

typename T::const_iterator iter;

如果不指定的话,编译器时无法知道这是一个类型还是一个成员变量的,下面的语句可以造成歧义:

T::const_iterator* pIter;

到底是声明一个指针变量还是拿T中的const_iterator
和 pIter相乘呢?编译器不知道!

3:不允许使用typename的地方:

1>typename T t;  这样是错误的,typename知识用来验证嵌套从属类型名称的,前面那句声明

编译器是很明确知道的,不需要加typename。

2>typename不能出现在base class list
和 member.init.list:                  */

template<typename T>

class Derived: public Base<T>::Nested          
//不需要typename
编译器知道的

{

public:

explicit Derived(int x) : Base<T>::Nested(x)   
//不需要使用typename

{

}

}

}

//#43   学习处理模版化基类内的名称

{

/*  如果基类是一个模版类,子类继承这样的基类时,如果想要调用基类的函数必须使用以下三种方法之一,否则

无法通过编译,因为基类是有可能特化的,所以编译器无法确定基类中是否真的存在你想调用的函数。比如你想

调用基类的sendClear:

1>使用this来调用:

this->sendClear();

2>使用using声明式:

using Base<T>::sendClear;

sendClear();

3>指明被调用的函数位于base中(不推荐使用这种方法)

Base<T>::sendClear()

不推荐的理由是,这种调用没有多态可言,如果sendClear是呈现多态,那么这里只会调用基类的函数。

但是换个思维来想,如果是virtual函数,那么子类中应该有相应实现吧。就不用别的操作,直接调用了。

(也就是一开始就通过编译了,不会考虑着三种方法了)

*/

}

//#44   将与参数无关的代码抽离templates

{

/*  1:使用template可以节省时间和避免代码重复,然而,看起来简洁的代码有可能会使代码的二进制码重复

而造成代码膨胀。

2:如何优化:

1>抽离相同的东西放入模版基类中。比如抽离相同的函数,相同的成员变量等。

2>当有需要时,可以给基类配置一个成员变量,抽离的函数
需要使用到的 一个指向子类中数据
的指针。

3:虽然做了这么多优化,但是需要付出一定的代码,简单来说就是执行速度。

这样的代码局部性不强,所以高速缓存很有可能无法命中。导致效率下降。

4:还有导致代码膨胀的情况:

1>int和long在很多平台上有相同的二进制表示,所以list<int>,list<long>实现的版本的二进制

表示是一样的,但是却实现了两份一样的代码。

2>所有的指针,比如list<const int*>, list<int>, list<Aclass*>这些底层实现应该唯一。

可以通过特化list<T*>来防止膨胀。

5:第一情况造成的膨胀应该考虑空间和时间,从中选择一个。

后面两种膨胀的情况时可以避免的。

*/

}

effective c++ 笔记 (41-44)的更多相关文章

  1. [Effective JavaScript 笔记]第44条:使用null原型以防止原型污染

    第43条中讲到的就算是用了Object的直接实例,也无法完全避免,Object.prototype对象修改,造成的原型污染.防止原型污染最简单的方式之一就是不使用原型.在ES5之前,并没有标准的方式创 ...

  2. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  3. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  4. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  5. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  6. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  7. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  8. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  9. Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer

    Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...

  10. Item 5:那些被C++默默地声明和调用的函数 Effective C++笔记

    Item 5: Know what functions C++ silently writes and calls 在C++中,编译器会自己主动生成一些你没有显式定义的函数,它们包含:构造函数.析构函 ...

随机推荐

  1. windows10如何打开vhd文件

    本人电脑安装了Visual Studio 2017,但是由于项目需求需要Core SDK(2.0)的版本支持,也就是2017最新版.所以现在需要利用visual Studio 2017最新版本的安装包 ...

  2. Django之cookie&session

    cookie Cookie 是在 HTTP 协议下,服务器或脚本可以维护客户工作站上信息的一种方式.Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息 ...

  3. CVE-2013-2551

    目录 小白的CVE-2013-2551 分析 & 利用 0xFF 前言 0x00 环境和工具 0x01 分析POC POC 调试 0x02 利用 构造R3任意内存读写 劫持eip 利用利用 0 ...

  4. div中嵌套div水平居中,垂直居中

    方法一: div(父):display:table; div(子):display:table_cell;margin:0 auto;vertical-align:middle; 方法二: div(父 ...

  5. 团队作业——Alpha冲刺 12/12

    团队作业--Alpha冲刺 冲刺任务安排 杨光海天 今日任务:自定义保存界面布局以及交互接口函数的实现 明日任务:总结项目中的问题,为什么没能按照预期推进项目 郭剑南 今日任务:继续解决Python编 ...

  6. R语言(资源)

    #学习 R 的方法 知识和耐心,是成为强者的唯一方法. - 通过阅读来学习.包括了阅读经典的教材.代码.论文.学习公开课.- 通过牛人来学习.包括同行的聚会.讨论.大牛的博客.微博.twitter.R ...

  7. SAP跟踪前台操作导致的后台查询语句

    SAP跟踪前台操作导致的后台查询语句,通过这个可以查看前台对应了后台的数据库表,然后可以通过se11查看表内容,也可以删除表内容. 在sap升级的时候,首先需要拷贝正式的sap系统,然后将拷贝的系统中 ...

  8. 漫画:高并发下的HashMap

    这一期我们来讲解高并发环境下,HashMap可能出现的致命问题. HashMap的容量是有限的.当经过多次元素插入,使得HashMap达到一定饱和度时,Key映射位置发生冲突的几率会逐渐提高. 这时候 ...

  9. Ant在MyEclipse中的配置总结

    1.在配置Ant之前,先要配置好JDK的JAVA_HOME和path:之后下载解压apache-ant-1.7.1;并配置环境变量ANT_HOME(安装目录,后不可以加分号:)及其path(安装目录/ ...

  10. Ubuntu18.04安装Teamviewer

    首先,打开TeamViewer的下载页面,下载Debian/Ubuntu的Deb安装包. 这里有64位和32位安装包选项.可以在Terminal(终端)中输入uname -a 查看自己系统版本是64位 ...