Effective C++ 随记 第七章(模板与泛型编程)

C++template 可以建立“类型安全”,还可以使得代码和其所处理对象类型彼此独立。

模板元编程: 在C++编译器内执行并于编译完成时停止执行。

条款41:了解隐式接口和编译期多态

面对对象编程中的显示接口和运行期多态(virtual 函数)比较重要,而 Template 和泛型编程中 隐式接口和编译器多态(template 具象化、函数重载)则更加重要。

隐式接口并不基于函数的签名式,由有效表达式组成。

template<typename T>

void doSomething(T& w){

if(w.size()>10 && w!= some){…}

}

上述隐式接口表示-类型T至少需要存在 成员函数size(),同时支持操作符 != 。

请记住:

1):class和template都支持接口和多态。

2):class的接口是显式的,以函数签名表示;多态是通过 virtual 函数发生于运行期。

3):template的接口是隐式的,基于有效表达式;多态由template具现化和函数重载解析发生于编译器。

 

条款42:了解 typename 的双重意义

从属名称: template 内出现的名称如果相依于某个 template 参数,称之为从属名称。

嵌套从属名称:如果从属名称在class内呈嵌套状。

template<typename C>    // tempale 的关键字前缀

void print2nd(const C& container){

typename C::const_iterator* x;  

// 标识为从属类型名称--指定C::const_iterator 为一种类型,否则的还也可能为某一变量。

}

请记住:

1):声明template时, 前缀关键字 class 和 typename 可互换。

2):使用关键词typename标识从属类型名称;但是不得在bass class list或者 成员处置列 中作为基类的修饰符。

 

条款43:学习处理模板化基类内的名称

模板类

template <typename T>

class send{…}

// 模板的全特化,及针对类型Companyz具象化

template <>

class send<Companyz>(){…}

模板化基类中可能存在特化具现的部分,因此其模板具现化出来的基类中可能存在不同的函数(特化部分)。在上述条件下,模板类继承中难以在基类中找寻基类,存在三种方式。

1:this->   可以调用基类函数;  ——  this->sendClear();

2:使用 using 声明式声明基类函数;——  using send<Companyz>::sendClear;

3:明确指定调用函数的类别: —— send<Companyz>::sendClear();

 请记住:

1):可在基类模板内通过 “this->”指涉基类内的成员名称,或者由一个明白写出的“基类资格修饰符”完成。

 

条款44:将与参数无关的代码抽离 template

请记住:

1):template生成多个class和多个函数,因此任何 template代码都不该与某个可能造成膨胀的template参数产生相依关系;

2):因非类型模板参数而造成的代码膨胀,可通过已函数参数或class成员变量替换tempalte参数来消除;

3):因参数类型而造成的代码膨胀,可以利用完全相同二级制表述的具现类型共享实现码。

 

条款45:运用成员函数模板接受所有兼容类型

template<typename T>

class smartPtr{

public:

template<typename U>

smartPtr(const smartPtr<U>& other);

}

上述代码中的构造函数表示可以根据 对像U 创建对象T。

请记住:

1):请使用成员函数模板生成“可接受所有兼容类型”的函数;

2):如果你声明的 成员模板 用于“泛化copy构造”或“泛化copy赋值操作“,还需要声明正常的copy构造函数和copy赋值操作函数。

 

条款46:需要转换类型时请为模板定义非成员函数

请记住:

1):当我们编写一个类模板,而它所提供的“于此template相关的”函数支持“所有参数的隐式类型转换”时,请将他定义为 类模板内部的friend函数。

 

条款47:请使用 traits class 表现类型信息

traits并不是关键字,而实预先定义好的构件,对于内置类型和用户定义的类型表现一样好。

类型的traits信息必须位于类型自身之外。

例如迭代器信息:

struct input_iterator_tag {};   // 输入迭代器

struct output_iterator_tag {};  // 输出迭代器

struct forward_iterator_tag: public input_iterator_tag {};  // 前向迭代器

struct bidirectional_iterator_tag: public forward_iterator_tag {};  // 双向迭代器

struct random_access_iterator_tag: public bidirectional_iterator_tag {};  // 随记迭代器

 

template<typename IterT>     //

struct iterator_traits;       // 迭代器分类相关

其运作方式为:针对每个类型 IterT,在struct iterato_traits<IterT>内,声明某个typdef 名为 iterator_category 作为类内的迭代器类型指代。

 

template<typename IterT, typename DistT>

void advance(TterT& iter, DisT d){

doadvance(iter, d, typename std::iterator_traits<IterT>::iterator_category()); // typename标识从属

// 第三个参数表示 IterT类中的 成员iterator_category,其为迭代器类型。

}

请记住:

1):trsits class使得 “类型信息”在编译器可用,通过template 及其特化实现。

2):整合重载技术后,trait class 有可能在编译器对类型执行 if…else 测试。

 

条款48:认识 template 元编程

typeid 用于在运行期获取变量类型。

模板元编程的优势:

1、确保度量单位正确(早期错误侦测);2、优化矩阵运算、3、生成客户定制的设计模式。

请记住:

1):模板元编程(TMP)可将工作由运行期移往编译器,可以获得更早期的进行错误侦测和更高的执行效率;

2):TMP可被用来生“基于政策选择组合”的客户定制代码,避免生成对某些特殊类型并不适合的代码。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值