读书笔记_Effective_C++_条款四十一:了解隐式接口和编译期多态
从本条款开始,就进入了全书的第七部分:模板与泛型编程。模板与泛型在C++中是非常重要的部分,还记得本书第一章时,把C++视为一个联邦,它由四个州政府组成,其中一个政府就是模板与泛型了。
本条款是一个介绍性质的条款,内容不难,只需要讲清楚两个概念就行了,即什么是隐式接口,什么是编译期多态。
隐式接口是相对于函数签名所代码的显式接口而言的。当我们看到一个函数签名(即函数声明),比如说:
string GetNameByStudentID(int StudentID);
我们就知道这个函数有一个整型的形参,返回值是string。
但隐式接口是由有效表达式组成的,考虑一个模板函数,像下面这样:
template <class T>
void TemplateFunction(T& w)
{
if(w.size() > ){…}
}
T可以是int,可以double,也可以是自定义的类型。光看这个函数声明,我们不能确定T具体是什么,但我们知道,要想通过编译,T必须要支持size()这个函数。也就是说,T中一定要有这样的函数接口声明。
ReturnValue size();
当然返回值ReturnValue不一定是int了,只要它能支持operator > (ReturnValue, 10)这样的运算即可。这种由表达式推判出来的函数接口,称之为隐式接口。
简言之,显式接口由函数签名式构成,隐式接口由有效的表达式组成。
下面讨论编译期多态的问题,我们在讨论继承时就已经多次提到“运行时多态”了,它伴随着virtual关键字,本质是一个虚表和虚指针,在类对象构造时,将虚指针指向了特定的虚表,然后运行时就会根据虚表的内容进行函数调用。
那么“编译期多态”又是什么呢,从字面上来看,它发生在编译阶段,实际上就是template <class T>这个T的替换,它可以被特化为int,或者double,或者用户自定义类型,这一切在编译期就可以决定下来T到底是什么,编译器会自动生成相应的代码(把T换成具体的类型),这就是编译期多态做的事情了,它的本质可以理解成自动生成特化类型版本,T可以被替换成不同的类型,比如同时存在int版本的swap与double版本的swap,形成函数重载。简言之,运行时多态是决定“哪一个virtual函数应该被绑定”,而编译期多态决定“哪一个重载函数应该被调用”。
最后总结一下:
1. class和template都支持接口与多态;
2. 对classes而言,接口是显式的,以函数签名为中心。多态则是通过virtual函数发生于运行期;
3. 对template参数而言,接口是隐式的,奠基于有效表达式。多态则是通过template具现化和函数重载解析发生于编译期。
读书笔记_Effective_C++_条款四十一:了解隐式接口和编译期多态的更多相关文章
- 读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第三部分)
下面来谈谈书中的第二部分,用Interface Classes来降低编译的依赖.从上面也可以看出,避免重编的诀窍就是保持头文件(接口)不变化,而保持接口不变化的诀窍就是不在里面声明编译器需要知道大小的 ...
- Effective C++ -----条款41:了解隐式接口和编译期多态
classes和templates都支持接口(interface)和多态(polymorphism). 对classes而言接口是显式的(explicit),以函数签名为中心.多态则是通过virtua ...
- 读书笔记_Effective_C++_条款四十九:了解new_handler的行为
本章开始讨论内存分配的一些用法,C/C++内存分配采用new和delete.在new申请内存时,可能会遇到的一种情况就是,内存不够了,这时候会抛出out of memory的异常.有的时候,我们希望能 ...
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
- 读书笔记_Effective_C++_条款四十七:请使用trait classes来表示类型信息
这一条款主要来讨论模板中迭代器的属性iterator_category,它可以通过类似于vector<int>::iterator::iterator_category的方式来取得. 到这 ...
- 读书笔记_Effective_C++_条款四十六:需要类型转换时请为模板定义非成员函数
这个条款可以看成是条款24的续集,我们先简单回顾一下条款24,它说了为什么类似于operator *这样的重载运算符要定义成非成员函数(是为了保证混合乘法2*SomeRational或者SomeRat ...
- 读书笔记_Effective_C++_条款四十五:运用成员函数模板接受所有兼容类型
比如有一个Base类和一个Derived类,像下面这样: class BaseClass {…}; class DerivedClass : public BaseClass {…}; 因为是父类与子 ...
- 读书笔记_Effective_C++_条款四十四:将与参数无关的代码抽离template
标题上说“将与参数无关的代码抽离template”,这里的参数既可以指类型,也可以是非类型,我们先来看看非类型的情况. 假定我们要为矩阵写一个类,这个矩阵的行列元素个数相等,是一个方阵,因而我们可以对 ...
- 读书笔记_Effective_C++_条款四十三:学习处理模板化基类的名称
背景是这样的,有两个不同的公司,然后想设计一个MessageSender,为这两个公司发送不同的消息,既支持明文发送SendClearText,也支持密文发送SendEncryptedText.一种思 ...
随机推荐
- Zabbix学习笔记一:基本安装与配置
1.下载安装 http://120.52.73.43/tenet.dl.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/3.0.1/za ...
- duilib进阶教程 -- 改进List控件 (16)
一.控件隐藏后,允许用代码操作所有行为. 在做播放器的时候,最常用的功能莫过于顺序播放.随机播放了,而当我们切换歌曲的时候,显然应该选中该歌曲,List的选中函数是SelectItem,但是调用此函数 ...
- es6学习笔记5--promise
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上说,Promise是一个对象,从它可以获取异步操作的消息.Promise提供统一的API, ...
- 第六章 应用层(DNS和http协议详解)
序言 这是计算机网络基础的最后一篇博文了,大体的从物理层到最上层的应用层做了一个大概的了解,花了也有快1个月的时间了,在本章结尾会给你们我学习该课程的视频资料,我希望能帮到所有想学习想提高自己技术的同 ...
- Java Socket网络编程常见异常(转)
1.java.net.SocketTimeoutException 这个异常比较常见,socket超时.一般有2个地方会抛出这个,一个是connect的时候,这个超时参数由connect(Socket ...
- 分享45个设计师应该见到的新鲜的Web移动设备用户界面PSD套件
对于一个网页设计师来说做一个好的PSD模板是非常有挑战性的一项任务,虽然PSD的模板简化了设计任务,但找出高质量的PSD文件,可以自由使用,是一 项艰巨的任务.你必须通过许多网页去找出一个极少数的PS ...
- WPF面板布局介绍Grid、StackPanel、DockPanel、WrapPanel
回顾 上一篇,我们介绍了基本控件及控件的重要属性和用法,我们本篇详细介绍WPF中的几种布局容器及每种布局容器的使用场景,当 然这些都是本人在实际项目中的使用经验,可能还存在错误之处,还请大家指出. 本 ...
- html5使用FileReader上传图片
客户端代码是网上找的,修改为.net代码. <html><head> <meta charset="utf-8"> <titl ...
- raspberry pi 如何汉化显示中文
1 树莓派初装系统之后,首次启动会出现“raspi-config”工具,如下图:(若不是初次启动,在命令模式下,请输入 sudo raspi-config 命令,即可调出此界面.若在图形桌面下,打开桌 ...
- DataGridView很详细的用法(转载)
一.DataGridView 取得或者修改当前单元格的内容: 当前单元格指的是 DataGridView 焦点所在的单元格,它可以通过 DataGridView 对象的 CurrentCell 属性取 ...