《Effective C++》学习笔记——条款41
2016-03-07 00:14
274 查看
七、模板与泛型编程
C++ template的最初动机 —— 让我们得以建立“类型安全”的容器,如 vector,list 和 map。而且 泛型编程写出的代码和其所处理的对象类型彼此独立。
C++ template机制自身是一部完整的图灵机:它可以被用来计算任何可计算的值。于是,导出了模板元编程,创造出“在C++编译器内执行并于编译完成时停止执行”的程序。
条款41、了解隐式接口和编译期多态
1. 显示接口 及 运行期多态
面向对象的世界总是以显示接口和运行期多态解决问题。class Widget { public: Widget(); virtual ~Widget(); virtual std::size_t size() const; virtual void normalize(); void swap(Widget& other); ... }; void doProcessing(Widget& w) { if( w.size() > 10 && w != someNastyWidget ) { Widget temp(w); temp.normalize(); temp.swap(w); } }
我们可以说doProcessing的w:
由于w的类型被声明为Widget,所以w必须支持Widget接口,我们可以在源码中找出接口(在.h文件中),所以它在源码中明确可见。
由于Widget的某些成员函数是virtual的,所以将在运行期根据w的动态类型决定调用哪个函数,即 w对那些函数的调用表现出运行期多态。
2. 隐式接口 及 编译器多态
将上述例子中的 doProcessing函数 转变为 函数模板template<typename T> void doProcessing(T& w) { if( w.size() > 10 && w != someNastyWidget ) { T temp(w); temp.normalize(); temp.swap(w); } }
再来说说doProcessing里的w
w必须支持哪一种接口,由template中执行于w身上的操作来决定。本例中,w的类型T必须支持size,normalize 和 swap成员函数、copy构造函数、不等比较等。
只要涉及w的任何函数调用,比如 operator > 与 !=,有可能造成template具现化,这样的具现行为发生在编译器。
“以不同的template参数具现化function templates”会导致调用不同的函数,这便是所谓的编译期多态。
3. 编译期多态 与 运行期多态 的 差异 and 显式接口 与 隐式接口 的 差异
编译期多态 与 运行期多态 的差异类似于 哪一个重载函数应该被调用(发生在编译期) 与 哪一个virtual函数该被绑定(发生在运行期)。显式接口 与 隐式接口 的差异可以通过例子来讲述:
通常 显式接口由函数的签名式(函数名称、参数类型、返回类型)构成,比如Widget类的 构造函数、析构函数、size、normalize、swap函数 及其 参数类型、返回类型、常量性,还有 编译器产生的 copy构造函数 与 copy assignment操作符。
此外,也可以包括 typedefs
class Widget { public: Widget(); virtual ~Widget(); virtual std::size_t size() const; virtual void normalize(); void swap(Widget& other); };
隐式接口就不同于此,并不基于函数签名式,而是由有效表达式组成。
template<typename T> void doProcessing(T& w) { if( w.size() > 10 && w != someNastyWidget ) { ... } }
T的隐式接口有这些约束
必须提供一个名为size的成员函数,该函数返回一个整数值。
必须支持一个 operator != 函数,用来比较两个T对象(此处假设 someNastyWidget类型为T)
隐式接口仅仅是由一组有效表达式构成,表达式自身可能看起来复杂,但它们要求的约束条件一般简单又明确。
在 template 参数身上的隐式接口,就像加在 class 对象身上的显式接口,两者都在编译期完成检查。
4. 请记住
class 和 template 都支持接口 和 多态对 class 而言接口是 显示的(explicit),以函数签名为中心;多态则是通过 virtual函数 发生于 运行期
对 template 参数而言,接口是 隐式的(implicit),奠基于有效表达式;多态则是通过template具现化 和 函数重载解析 发生于编译期
相关文章推荐
- c++ primer 第五版 笔记前言
- 那些年,我还在学习C# 学习笔记续
- Ruby 魔法 学习笔记之一
- sqlserver 数据库学习笔记
- CSS学习笔记Padding 属性中参数的定义与使用
- prototype 1.5 & scriptaculous 1.6.1 学习笔记
- prototype 学习笔记整理
- Oracle学习笔记(六)
- 关于SQLServer2005的学习笔记 XML的处理
- Jquery 基础学习笔记
- ExtJs 学习笔记基础篇 Ext组件的使用第1/2页
- linux Shell学习笔记第五天
- Jquery 学习笔记(二)
- PHP入门学习笔记之一
- 那些年,我还在学习C# 学习笔记
- Ruffy javascript 学习笔记
- JavaScript 学习笔记(十六) js事件
- JavaScript 学习笔记(十二) dom
- JavaScript 学习笔记(十一)
- JavaScript 学习笔记 Black.Caffeine 09.11.28