//---------------------------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. 为notifyIcon.icon属性赋图片

    System.Drawing.Bitmap bp; bp = new Bitmap(Application.StartupPath + @"\image\" + MeiYeShuo ...

  2. leveldb源码分析--SSTable之逻辑结构

    SSTable是leveldb 的核心模块,这也是其称为leveldb的原因,leveldb正是通过将数据分为不同level的数据分为对应的不同的数据文件存储到磁盘之中的.为了理解其机制,我们首先看看 ...

  3. HttpWebRequest抓取网页内容与直接输入URL得到的内容不一致!球大神帮忙!!

    一.前言 我在做一个百度收录情况查询的软件,就是通过软件来批量查询文章链接是否被百度收录,主要是用来查询某个网址的收录次数还有网站的排行数,思路是借鉴别人的. 二.问题描述 首先需要考虑的是能够支持哪 ...

  4. [原创]使MySQL注释语句在后台能够输出的方法

    开启general log或slow log的时候,前端发出的sql语句中的注释都别屏蔽掉了. 本意加注释我们想通过注释来快速知道sql是由哪个业务模块发出的.这点对dba和研发很有帮助. 一种变通的 ...

  5. C#读取AD域用户信息

    private const string domainName = "本机IP地址或域名"; private const string adAdmin = "管理员帐号& ...

  6. QT的setwindowflags的属性总结

    :setWindowFlags(Qt::CustomizeWindowHint);//设置窗口标题栏自定义 setWindowFlags(Qt::WindowMinimizeButtonHint);/ ...

  7. DOS 总结

    shutdown -s -t 30 指定在30秒之后自动关闭计算机. + L 返回登录页面 netstat 最近访问IP Regedit 打开注册表

  8. October 10th 2017 Week 41st Tuesday

    If you focus on what you left behind you will never see what lies ahead. 如果你只顾回头看,那么你永远也看不见前方有什么. Ye ...

  9. JAVA内存管理 [转]

    首先我们要明白一点,我们所使用的变量就是一块一块的内存空间!!   一.内存管理原理:   在java中,有java程序.虚拟机.操作系统三个层次,其中java程序与虚拟机交互,而虚拟机与操作系统间交 ...

  10. Sublime2 DocBlocker插件在自动补全注释时输出自定义作者和当前时间等信息

    Sublime在进行前端开发时非常棒,当然也少不了众多的插件支持,DocBlocker是在Sublime平台上开发一款自动补全代码插件,支持JavaScript (including ES6), PH ...