《c++ primer》第16章 模板与泛型编程
来源:互联网 发布:java runnable thread 编辑:程序博客网 时间:2024/04/29 03:42
泛型编程就是独立于任何特定类型的方式进行编码。模板是泛型编程的基础。使用模板无需了解模板的定义。依赖于编译时的多态性或参数式多态性
模板的定义
- 函数模板定义
template <typename T>int compare(const T &v1,const T &v2){ if(v1<v2) return -1; if(v2>v1) return 1; return 0;}
模板形参表<typename T>- 类模板
template <class Type>class Queue{ public: Queue(); Type &front(); ......}
- 非类型模板形参
template<class T,size_t N>void array_init(T (&parm)[N]){ for(size_t i = 0;i!= N;++i) { parm[i] = 0; }}
在需要常量表达式的时候,可使用非类型形参指定数组长度int x[42];array_init(x); //初始化 array_init(int (&)[42])
- 编写模板代码的时候,对实参类型要求尽可能的少是有益的
模板的实例化
- 多个类型的实参完全匹配
template<typename T>int compare(const T& v1,const T& v2){ ......}int main(){ short si; compare(si,1024);//error 应该同为相同的类型 return 0;}
- (稍加注意)类型的实参形参受限转换:const转换,数组或函数到指针转换。
template<T> T fobj(T,T);template<T> T fref(const T&,const T&);string s1("a value");const string s2("another value");fobj(s1,s2); //全部变换为非const类型fref(s1,s2); //转换为const类型int a[10];int b[42];fobj(a,b); //可以将数组名转换为指针fref(a,b); //错误,不能将数组名转换为指针
模板编译类型
- 当编译器看到模板的时候,并不立即产生代码,只有用到模板的时候,如调用了函数模板或定义了类模板的对象的时候,编译器才产生特定类型的模板实例。
- 区别:调用函数的时候,编译器只需要看到函数的声明。类似,定义类类型的对象,类定义必须可以使用,但成员函数的定义不一定要存在。所以将类定义和函数声明放在头文件中,函数和成员函数的定义放在源文件中。模板不同,要进行实例化,编译器必须能够访问定义模板的源代码
- 标准c++为编译模板定义了两种类型。不同之处在于如何使用源文件中的定义。
- 包含模型:编译器必须看到所有模板的定义,所以在头文件中添加#include指示。编译效率比较差,会有多个实例化,优化来避免
- 分别编译模型:export关键字。指明给定的定义可能需要在其他文件中产生实例化。在一个文件中,一个模板只能定义为导出一次。头文件中类或函数不能声明为export,一般在源文件中的函数定义以及类的定义源文件中声明为export。
类模板成员
- 何时实例化类和成员?类模板成员只有为程序所用才进行初始化。如果某函数从未使用过,则不会实例化该成员函数
- (有意思)类模板中的友元声明:a将友元关系授予明确的指定的类或函数 b授予对友元所有类型的访问权限 c只授予对类模板或函数模板的特定实例的访问权的友元声明
//情况btemplate <class Type>class Bar{ template<class T>friend class Fool; template<class T>friend void templ_fcn1(const T&);}//情况c,只有给定与bar实例有相同模板实参的Foo2和fcn2,才可以为友元template <class T>class Foo2;template <class T>class templ_fcn2(const T&)template <class Type>class Bar{ friend class Foo2<Type>; friend void <Type>templ_fcn2(const Type&);}
- 成员模板(定义两个模板形参)
template<class Type>class Queue{public: template<class It> Queue(It beg,It end):head(0),tail(0){ ......} ......}
//外部定义的时候,必须含有两个模板形参template<class T>template<class Iter>void Queue<T>::assign(Iter beg,Iter end){ destroy(); copy_elems(beg,end);}
- static成员,每个实例化都有自己的static成员
//分享同一个static成员Foo<int> fi,fi2,fi3;//单独的static成员Foo<string>fs
- Queue与QueueItem完整定义
#include <iostream>// declaration that Queue is a template needed for friend declaration in QueueItemtemplate <class Type> class Queue;// function template declaration must precede friend declaration in QueueItemtemplate <class T> std::ostream& operator<<(std::ostream&, const Queue<T>&);template <class Type> class QueueItem { friend class Queue<Type>; // . . . // needs access to item and next friend std::ostream& operator<< <Type> (std::ostream&, const Queue<Type>&); // . . .// private class: no public section QueueItem(const Type &t): item(t), next(0) { } Type item; // value stored in this element QueueItem *next; // pointer to next element in the Queue};template <class Type> class Queue { // needs access to head friend std::ostream& operator<< <Type> (std::ostream&, const Queue<Type>&);public: // empty Queue Queue(): head(0), tail(0) { }public: // construct a Queue from a pair of iterators on some sequence template <class It> Queue(It beg, It end): head(0), tail(0) { copy_elems(beg, end); } // . . . // copy control to manage pointers to QueueItems in the Queue Queue(const Queue &Q): head(0), tail(0) { copy_elems(Q); } Queue& operator=(const Queue&); ~Queue() { destroy(); } // replace current Queue by contents delimited by a pair of iterators template <class Iter> void assign(Iter, Iter); // rest of Queue class as before // return element from head of Queue // unchecked operation: front on an empty Queue is undefined Type& front() { return head->item; } const Type &front() const { return head->item; } void push(const Type &); // add element to back of Queue void pop(); // remove element from head of Queue bool empty() const { // true if no elements in the Queue return head == 0; }private: QueueItem<Type> *head; // pointer to first element in Queue QueueItem<Type> *tail; // pointer to last element in Queue // utility functions used by copy constructor, assignment, and destructor void destroy(); // delete all the elements void copy_elems(const Queue&); // copy elements from parameterprivate: // version of copy to be used by assign to copy elements from iterator range template <class Iter> void copy_elems(Iter, Iter); };
需要注意的是:输出函数不是成员函数,而是两个类的友元; QueueItem中声明了一对一的友元Queue; Queue中有成员模板的定义
- [C/C++] 第16章 模板与泛型编程 《 C++ Primer 》
- 《C++ Primer》 第16章 模板与泛型编程
- 《c++ primer》第16章 模板与泛型编程
- 《c++ primer》 第16章 模板与泛型编程
- 《C++Primer》读书笔记——第16章 模板与泛型编程
- 【c++primer】第十六章:模板与泛型编程
- C++ primer第二次阅读学习笔记(第16章:模板与泛型编程) .
- 《C++ primer(第四版)》读书笔记7-第16章 模板与泛型编程
- 《C++ Primer》 第四版 第16章 模板与泛型编程
- 《C++ Primer》读书笔记 第16章:模板与泛型编程
- C++ Primer 第16章 模板与泛型编程 学习笔记
- c++ primer 16章 模板与泛型编程
- 《C++Primer》 3.19 模板与泛型编程
- c++primer要点-模板与泛型编程
- C++Primer---模板与泛型编程(一)
- C++Primer笔记 十六 模板与泛型编程
- C++primer阅读笔记----------模板与泛型编程
- 《C++ Primer 4 Answer Book》 整理[15]——第16章 模板与泛型编程
- 创建线程的两种方式
- mysql如何修改字符编码
- ios6 屏幕旋转
- SQL 2005修改数据库表的创建时间
- linux crontab 定时任务 命令详解
- 《c++ primer》第16章 模板与泛型编程
- 一位大牛整理的Python资源
- Win7任务管理器显示不全问题解决办法
- qt添加头文件和库文件
- solr取所有文档示例
- SSH 登录问题 (生成RSA Key,无密码登录,root SSH登录,etc.)
- struts2中action调用servletAPI方法及struts2标签显示方式
- 错误Set connectionId threw an exception
- ORACLE 数据块、ITL SELECT和UPDATE逻辑梳理