【effective c++】模板与泛型编程

1.了解隐式接口和编译期多态

对template参数而言,接口是隐式的,基于有效表达式的约束

编译器多态:以不同的template参数具现化function templates会导致调用不同的函数

2.了解typename的双重意义

当我们声明template类型参数,class和typename的意义完全相同

template内出现的名称如果相依于某个template参数,称之为从属名称,如果从属名称在class内呈嵌套状,称之为嵌套从属名称。c++规定:如果解析器在template中遭遇一个嵌套从属名称,它便假设这名称不是个类型,除非你告诉它是。

任何时候当你想要在template中指涉一个嵌套从属类型名称,就必须在紧邻它的前一个位置放上关键字typename,typename只被用来验明嵌套从属类型名称,其他名称不该有它存在

template <typename C>
void f(const  C& container,        //不允许使用typename
    typename C::iterator iter); //一定要使用typename

typename必须作为嵌套从属类型名称的前缀词这一规则的例外是,typename不可以出现在base class list内的嵌套从属类型名称之前,也不可在成员初始化列表中作为base class修饰符

template <typename T>
class Derived :public Base<T>::Nested
{
public:
    explicit Derived(int x)
        :Base<T>::Nested(x)
    {
        typename Base<T>::Nested temp;
    }
};
std::iterator_traits<IterT>::value_type  //类型为IterT之对象所指之物的类型

真实程序中使用typename的例子:

template <typename IterT>
void workWithIterator(IterT iter)
{
    typename std::iterator_traits<IterT>::value_type  temp(*iter);
}

3.学习处理模板化基类内的名称

base class template有可能被特化,而那个特化版本可能不提供和一般性template相同的接口,故c++往往拒绝在模板化基类内寻找继承而来的名称

解决方案:对编译器承诺base class template的任何特化版本都将支持其一般(泛化)版本所提供的接口

1)在base class函数调用动作之前加上"this ->"

2)使用using声明式

3)明确指出被调用的函数位于base class内即用基类名称去调用该函数,这样会失去多态性

4.将与参数无关的代码抽离template?

5.运用成员函数模板接受所有兼容类型

同一个template的不同具现化之间并不存在什么固有关系,如果以带有base-derived关系的B、D两类型分别具现化某个template,产生出来的两个具现体并不带有base-derived关系

template<typename T>
class SmartPtr
{
public:
    template<typename U>
    //对任何类型T和任何类型U,可以根据SmartPtr<U>生成一个SmartPtr<T>
    SmartPtr(const SmartPtr<U>& other);
};

6.需要类型转换时请为模板定义非成员函数

当我们编写一个class template,而它所提供之"与此template相关的"函数支持"所有参数之隐式类型转换"时,请将那些函数定义为class template内部的friend函数

7.请使用traits classes表现类型信息

traits并不是c++关键字或一个预先定义好的构件,它是一种技术,也是每一个c++程序员共同遵守的协议,允许你在编译期取得某些类型信息,traits总是被实现为struct,iterator_traits是针对迭代器的traits

iterator_traits的运作方式是,针对每一个类型IterT,在struct iterator_traits<IterT>内一定声明某个typedef名为iterator_category,为此它要求每一个用户自定义的迭代器类型必须嵌套一个typedef,名为iterator_category.

iterator_traits特别针对指针类型提供一个偏特化版本:

template<typename IterT>
struct iterator_traits(IterT*)
{
    typedef random_access_iterator_tag iterator_category;
};

总结:

1)traits classes使得类型相关信息在编译器可用,它们以templates和templates特化完成实现

2)整合函数重载技术后,traits classes有可能在编译期对类型执行if...else测试

时间: 2024-10-11 19:05:14

【effective c++】模板与泛型编程的相关文章

Effective C++ —— 模板与泛型编程(七)

条款41 : 了解隐式接口和编译器多态 1 条款42 : 了解typename的双重意义 1

C++ 模板与泛型编程

<C++ Primer 4th>读书笔记 所谓泛型编程就是以独立于任何特定类型的方式编写代码.泛型编程与面向对象编程一样,都依赖于某种形式的多态性. 面向对象编程中的多态性在运行时应用于存在继承关系的类.我们能够编写使用这些类的代码,忽略基类与派生类之间类型上的差异. 在泛型编程中,我们所编写的类和函数能够多态地用于跨越编译时不相关的类型.一个类或一个函数可以用来操纵多种类型的对象. 面向对象编程所依赖的多态性称为运行时多态性,泛型编程所依赖的多态性称为编译时多态性或参数式多态性. 模板是泛型

C++ Primer 学习笔记_77_模板与泛型编程 --实例化

模板与泛型编程 --实例化 引言: 模板是一个蓝图,它本身不是类或函数.编译器使用模板产生指定的类或函数的特定版本号.产生模板的特定类型实例的过程称为实例化. 模板在使用时将进行实例化,类模板在引用实际模板类型时实例化,函数模板在调用它或用它对函数指针进行初始化或赋值时实例化. 1.类的实例化 当编写Queue<int>qi时,编译器自己主动创建名为Queue<int>的类.实际上,编译器通过又一次编写Queue模板,用类型int取代模板形參的每次出现而创建Queue<int

C++ Primer 学习笔记_81_模板与泛型编程 --类模板成员[续1]

模板与泛型编程 --类模板成员[续1] 二.非类型形参的模板实参 template <int hi,int wid> class Screen { public: Screen():screen(hi * wid,'#'), cursor(hi * wid),height(hi),width(wid) {} //.. private: std::string screen; std::string::size_type cursor; std::string::size_type height

C++ Primer 学习笔记_82_模板与泛型编程 --类模板成员[续2]

模板与泛型编程 --类模板成员[续2] 六.完整的Queue类 Queue的完整定义: template <typename Type> class Queue; template <typename Type> ostream &operator<<(ostream &,const Queue<Type> &); template <typename Type> class QueueItem { friend clas

C++ Primer 学习笔记_76_模板和泛型编程 --模板定义[继续]

模板和泛型编程 --模板定义[续] 四.模板类型形參 类型形參由keywordclass或 typename后接说明符构成.在模板形參表中,这两个keyword具有同样的含义,都指出后面所接的名字表示一个类型. 模板类型形參可作为类型说明符在模板中的不论什么地方,与内置类型说明符或类类型说明符的使用方式全然同样. 详细而言,它能够用于指定返回类型或函数形參类型,以及在函数体中用于变量声明或强制类型转换. template <class T> T calc(const T &a,cons

C++ Primer 学习笔记_75_模板与泛型编程 --模板定义

模板与泛型编程 --模板定义 引言: 所谓泛型程序就是以独立于不论什么特定类型的方式编写代码.使用泛型程序时,我们须要提供详细程序实例所操作的类型或值. 模板是泛型编程的基础.使用模板时能够无须了解模板的定义. 泛型编程与面向对象编程一样,都依赖于某种形式的多态性.面向对象编程中的多态性在执行时应用于存在继承关系的类.我们能够编写使用这些类的代码,忽略基类与派生类之间类型上的差异.仅仅要使用基类的引用或指针,基类类型或派生类类型的对象就能够使用同样的代码. 在泛型编程中,我们所编写的类和函数能够

C++ Primer 学习笔记_84_模板与泛型编程 --模板特化

模板与泛型编程 --模板特化 引言: 我们并不总是能够写出对全部可能被实例化的类型都最合适的模板.某些情况下,通用模板定义对于某个类型可能是全然错误的,通用模板定义或许不能编译或者做错误的事情;另外一些情况下,能够利用关于类型的一些特殊知识,编写比从模板实例化来的函数更有效率的函数. compare函数和 Queue类都是这一问题的好样例:与C风格字符串一起使用进,它们都不能正确工作. compare函数模板: template <typename Type> int compare(cons

C++ Primer 学习笔记_83_模板与泛型编程 --一个泛型句柄类

模板与泛型编程 --一个泛型句柄类 引言: [小心地雷] 这个例子体现了C++相当复杂的语言应用,理解它需要很好地理解继承和模板.在熟悉了这些特性之后再研究这个例子也许会帮助.另一方面,这个例子还能很好地测试你对这些特性的理解程度. 前面示例的Sales_item和Query两个类的使用计数的实现是相同的.这类问题非常适合于泛型编程:可以定义类模板管理指针和进行使用计数.原本不相关的Sales_item类型和 Query类型,可通过使用该模板进行公共的使用计数工作而得以简化.至于是公开还是隐藏下

C++ primer 模板与泛型编程

继续浏览c++ primer 看到模板与泛型编程这章,就顺便把这几节的代码综合了下,对一个Queue队列模板的实现 贴一下代码(看完书,自己敲,忘记了哪再看下书) #include <ostream> using std::ostream; //声明Queue的模板类 template <class Type> class Queue; //声明模板函数 template <class T> ostream& operator<<(ostream&a