钱能C++程序设计教程14
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
03:4Βιβλιοθήκη Baidu:22 9
引用型形参
其数据形参与数据实参捆绑,故数据实参应为左值表达式:
template<typename T> void swap(T& a, T& b){ T t=a; a=b; b=t; } int main(){ int ia=3; const int cb=5; swap(ia, 7); swap<int>(ia, 7); swap(cb, 7); swap<const int>(ia, 7); }
template<typename T> class Node{ public: Node(const T& d):c(d),next(0),pref(0){} T c; Node *next, *pref; };
03:40:22
13
又例如下面的模板类定义,含 有模板类的成员:
template<typename T> class List{ Node<T> *first, *last; public: List(); void add(const T& c); void remove(const T& c); Node<T>* find(const T& c)const; void print()const; ~List(); };
第一次用特定的类型实参使用模板函数 时,将引起函数模板的实例化(产生 函数定义).
03:40:22 19
实例化与实施的操作有关,构造对象 所触发的实例化,只实例化其构造函 数,不实例化类模板的其他成员函 数.但可以通过显式请求,强制整体 实例化.
template List<int>;//实例化整个模板类 List<double> dList;//实例化构造函数 dList.add(3.6);//实例化add成员 dList.add(5.8);//不再实例化,只是简单调用 List<int> iList;//不再实例化 iList.add(5);//不再实例化
03:40:22 21
模板铸件可为类,亦可为模板.若 为模板,则其定做称为局部定做.
template<typename T1, typename T2> class A{ ... }; 局部定做1 template<typename T> class A<T, T>{ … }; //A<T, T>为模板 局部定做2 template<typename T> class A<T, Cat>{ … }; //A<T, Cat>为模板 使用时要注意: A<double,Cat> dCat; //按A<T,Cat>匹配 A<double,double> dd;//按A<T,T>匹配 A<Cat,Cat> cCat; //错:A<T,Cat>还是A<T,T>?
编程方法的侧重点
面向对象编程解决类体系中的不同对象行 为表现 模板编程解决独立类之间的不同对象行为 表现 多个独立类可以是多个类继承体系,因而, 面向对象编程与模板编程是融合的.
03:40:22 2
第十四章内容
1. 2. 3. 4. 5. 6. 7.
03:40:22
函数模板(Function Template) 函数模板 函数模板参数(Function Template Parameter) 函数模板参数 类模板(Class Template) 类模板 实例化与定做(Instantiation & Specialization) 实例化与定做 程序组织(Program Organization) 程序组织 模板的多态(Template Polymorphism) 模板的多态 高级编程(Advanced Programming) 高级编程
15
03:40:22
类模板(class template):侧重于模板的描述 (声明或定义),例如: Template<typename T>class List;//类模板声明 template<typename T> //类模板定义 class List{ Node<T> *first, *last; public: List(); void add(const T& c); void remove(const T& c); Node<T>* find(const T& c)const; void print()const; ~List(); 模板类(template class):侧重于模板的使用形式 }; 例如: List<T> //T为类型形参 List<Dog> //Dog是类型实参 形如List<T>形式的类,不管T是形参还是实参,本 书都称之为为模板类
// // // //
error:7不是左值 不是左值 error:哪怕类型指定也不济 哪怕类型指定也不济 error:const int会引起操作错误 会引起操作错误 error:同上 同上
03:40:22
10
函数模板重载
参数有不同的形式(是否引用,是否常量,甚至是否特殊类型),不同形式 的参数,其行为不同,这是模板重载的前提. 例如:字串比较很特殊,指针比较与对象比较亦不同,则:
03:40:22
14
与类定义相似,成员函数的定义一般放在 类定义的外部,与类定义分开.以有利于 程序的组织.放在模板类定义外部的成员 函数的定义形式为:
template<typename T> List<T>::List():first(0),last(0){}
List构造函数
template<typename T> void List<T>::add(const T& n){ Node<T>* p = new Node<T>(n); p->next = first; first = p; (last ? p->next->pref : last) = p; }
template<typename T> T const& max(T const& a, T const& b){ return a < b ? b : a; } template<typename T> T* const& max(T* const& a, T* const& b){ return *a < *b ? b : a; } const char* const& max(const char* const& a, const char* const& b){ return strcmp(a,b) < 0 ? b : a; } int main(){ int ia=3, ib=7; char *s1="hello", *s2="hell"; cout<<*max(&ia, &ib)<<"\n"; // match the second template cout<<max(s1, s2)<<"\n"; // match the max function cout<<max(ia, ib)<<"\n"; // match the first template 03:40:22 11 }
3
1. 函数模板 ( Function Template )
理想的函数重载是针对不同的参 数做不同的事. 而形如:
void swap(Type& a, Type& b){ Type t=a; a=b; b=t; }
的重载函数系所定义的行为序列 却相同.这种形式的重载意义 不大.
03:40:22 4
03:40:22 18
4. 实例化与定做 ( Instantiation & Specialization )
实例化遵循一次定义原则 第一次用特定的类型实参使用模板类时, 将引起类模板的实 例化(产生类 定 义). )
List<double> dList;//产生实例化 List<double> eList;//不再实例化
C++程序设计教程(第二版)
第十四章 模板 Chapter 14 Template
清华大学出版社 钱 能
03:40:22
1
思考角度
C++程序是一些类型和函数,编程就是设计 类型和函数,然后按C++的程序结构来组织
模板编程
世界上万事万物都具有相似性,许多类型 和函数尽管处理的数据不同,但其行为也 具有相似性,将相似的类型归为类型族以 及相似的函数归为函数族的编程,就是模 板编程
3. 类模板 ( Class Template )
有些类,比如容器类,处理一种类 型的对象与处理另一种类型的对象 方法一样,但是就因为处理的对象 类型不同,而使该类必须重新定 义.例如: CatList, DogList, RabbitList等
03:40:22
12
通过模板类定义,可以解决代码冗繁问题:
03:40:22
20
对于特定的类型实参,希望其行为不同于类 模板所规定的操作,可以根据该实参来 定做,定做的模板称为模板铸件(或称 特制模板),如:
template<> class List<Cat>{ Node<Cat> *first, *last; public: List(); void add(const Cat& c); void remove(const Cat& c); Node<Cat>* find(const Cat& c)const; void print()const; ~List(); };
定义函数模板来表示重载函数系:
模板形参
函数模板名
template<typename T> void swap(T& a, T& b) { T t=a; a=b; b=t; }
函数模板 定义体
数据形参
03:40:22
5
函数模板用法: 以函数模板名作调用的函数名,以数据 实参作参数传递
template<typename T> void swap(T& a, T& b){ T t=a; a=b; b=t; } int fn(){ int ix=6, iy=7, ia=3, ib=5; swap(ix, iy); //产生函数定义体 swap(ia, ib); //不产生函数定义体 //... }
03:40:22 7
数据形参分: 引用型参数(提倡用本项) 非引用型参数 引用型参数分: 引用型参数 常量引用型参数
03:40:22
8
常量引用型形参
其数据形参可以是临时对象,所以,通过显式转换可以 规定模板的产生形式.但是,不能被隐式转换的数 据形参,其显式模板类型指定失效:
template<typename T> T const& max(T const& a, T const& b){ return a < b ? b : a; } int main(){ int ia=3; double db=6.7; db = max<double>(ia, db); db = max(static_cast<double>(ia), db); db = max<double>(&ia, db); //error }
03:40:22 16
高级模板概念中,类模板声明,如: Template<typename T>class List 等同于带有形式类型参数的模板类,如: List<T> 并将其作为一种类型看待 所以本质上不区分类模板与模板类.
03:40:22
17
模板类的使用将直接透入对象的构造,因此, 允许模板类带有值参便理所当然了. template<unsigned int N> class bitset; 但是类型值参将导致不同的类模板描述,因 而决定了不同的值参值,生成不同的模板类 bitset<100> a; bitset<200> b; a = b; // error 值参值应为编译能识别的常量,值参多为整 型.
03:40:22 6
2. 函数模板参数 ( Function Template Parameter )
数据参数是按值的性质匹配的,所以相容 类型之间可以转换 类型参数是按名字匹配的,更为苛刻
template<typename T> void swap(T& a, T& b){ T t=a; a=b; b=t; } int add(double a, double b){ return a+b; } int fn(){ int ia=3; double db=5.0; char s1[]="good", s2[]="better"; int x = add(ia, db); // ok swap(ia, db); // error swap(s1, s2); // error }
引用型形参
其数据形参与数据实参捆绑,故数据实参应为左值表达式:
template<typename T> void swap(T& a, T& b){ T t=a; a=b; b=t; } int main(){ int ia=3; const int cb=5; swap(ia, 7); swap<int>(ia, 7); swap(cb, 7); swap<const int>(ia, 7); }
template<typename T> class Node{ public: Node(const T& d):c(d),next(0),pref(0){} T c; Node *next, *pref; };
03:40:22
13
又例如下面的模板类定义,含 有模板类的成员:
template<typename T> class List{ Node<T> *first, *last; public: List(); void add(const T& c); void remove(const T& c); Node<T>* find(const T& c)const; void print()const; ~List(); };
第一次用特定的类型实参使用模板函数 时,将引起函数模板的实例化(产生 函数定义).
03:40:22 19
实例化与实施的操作有关,构造对象 所触发的实例化,只实例化其构造函 数,不实例化类模板的其他成员函 数.但可以通过显式请求,强制整体 实例化.
template List<int>;//实例化整个模板类 List<double> dList;//实例化构造函数 dList.add(3.6);//实例化add成员 dList.add(5.8);//不再实例化,只是简单调用 List<int> iList;//不再实例化 iList.add(5);//不再实例化
03:40:22 21
模板铸件可为类,亦可为模板.若 为模板,则其定做称为局部定做.
template<typename T1, typename T2> class A{ ... }; 局部定做1 template<typename T> class A<T, T>{ … }; //A<T, T>为模板 局部定做2 template<typename T> class A<T, Cat>{ … }; //A<T, Cat>为模板 使用时要注意: A<double,Cat> dCat; //按A<T,Cat>匹配 A<double,double> dd;//按A<T,T>匹配 A<Cat,Cat> cCat; //错:A<T,Cat>还是A<T,T>?
编程方法的侧重点
面向对象编程解决类体系中的不同对象行 为表现 模板编程解决独立类之间的不同对象行为 表现 多个独立类可以是多个类继承体系,因而, 面向对象编程与模板编程是融合的.
03:40:22 2
第十四章内容
1. 2. 3. 4. 5. 6. 7.
03:40:22
函数模板(Function Template) 函数模板 函数模板参数(Function Template Parameter) 函数模板参数 类模板(Class Template) 类模板 实例化与定做(Instantiation & Specialization) 实例化与定做 程序组织(Program Organization) 程序组织 模板的多态(Template Polymorphism) 模板的多态 高级编程(Advanced Programming) 高级编程
15
03:40:22
类模板(class template):侧重于模板的描述 (声明或定义),例如: Template<typename T>class List;//类模板声明 template<typename T> //类模板定义 class List{ Node<T> *first, *last; public: List(); void add(const T& c); void remove(const T& c); Node<T>* find(const T& c)const; void print()const; ~List(); 模板类(template class):侧重于模板的使用形式 }; 例如: List<T> //T为类型形参 List<Dog> //Dog是类型实参 形如List<T>形式的类,不管T是形参还是实参,本 书都称之为为模板类
// // // //
error:7不是左值 不是左值 error:哪怕类型指定也不济 哪怕类型指定也不济 error:const int会引起操作错误 会引起操作错误 error:同上 同上
03:40:22
10
函数模板重载
参数有不同的形式(是否引用,是否常量,甚至是否特殊类型),不同形式 的参数,其行为不同,这是模板重载的前提. 例如:字串比较很特殊,指针比较与对象比较亦不同,则:
03:40:22
14
与类定义相似,成员函数的定义一般放在 类定义的外部,与类定义分开.以有利于 程序的组织.放在模板类定义外部的成员 函数的定义形式为:
template<typename T> List<T>::List():first(0),last(0){}
List构造函数
template<typename T> void List<T>::add(const T& n){ Node<T>* p = new Node<T>(n); p->next = first; first = p; (last ? p->next->pref : last) = p; }
template<typename T> T const& max(T const& a, T const& b){ return a < b ? b : a; } template<typename T> T* const& max(T* const& a, T* const& b){ return *a < *b ? b : a; } const char* const& max(const char* const& a, const char* const& b){ return strcmp(a,b) < 0 ? b : a; } int main(){ int ia=3, ib=7; char *s1="hello", *s2="hell"; cout<<*max(&ia, &ib)<<"\n"; // match the second template cout<<max(s1, s2)<<"\n"; // match the max function cout<<max(ia, ib)<<"\n"; // match the first template 03:40:22 11 }
3
1. 函数模板 ( Function Template )
理想的函数重载是针对不同的参 数做不同的事. 而形如:
void swap(Type& a, Type& b){ Type t=a; a=b; b=t; }
的重载函数系所定义的行为序列 却相同.这种形式的重载意义 不大.
03:40:22 4
03:40:22 18
4. 实例化与定做 ( Instantiation & Specialization )
实例化遵循一次定义原则 第一次用特定的类型实参使用模板类时, 将引起类模板的实 例化(产生类 定 义). )
List<double> dList;//产生实例化 List<double> eList;//不再实例化
C++程序设计教程(第二版)
第十四章 模板 Chapter 14 Template
清华大学出版社 钱 能
03:40:22
1
思考角度
C++程序是一些类型和函数,编程就是设计 类型和函数,然后按C++的程序结构来组织
模板编程
世界上万事万物都具有相似性,许多类型 和函数尽管处理的数据不同,但其行为也 具有相似性,将相似的类型归为类型族以 及相似的函数归为函数族的编程,就是模 板编程
3. 类模板 ( Class Template )
有些类,比如容器类,处理一种类 型的对象与处理另一种类型的对象 方法一样,但是就因为处理的对象 类型不同,而使该类必须重新定 义.例如: CatList, DogList, RabbitList等
03:40:22
12
通过模板类定义,可以解决代码冗繁问题:
03:40:22
20
对于特定的类型实参,希望其行为不同于类 模板所规定的操作,可以根据该实参来 定做,定做的模板称为模板铸件(或称 特制模板),如:
template<> class List<Cat>{ Node<Cat> *first, *last; public: List(); void add(const Cat& c); void remove(const Cat& c); Node<Cat>* find(const Cat& c)const; void print()const; ~List(); };
定义函数模板来表示重载函数系:
模板形参
函数模板名
template<typename T> void swap(T& a, T& b) { T t=a; a=b; b=t; }
函数模板 定义体
数据形参
03:40:22
5
函数模板用法: 以函数模板名作调用的函数名,以数据 实参作参数传递
template<typename T> void swap(T& a, T& b){ T t=a; a=b; b=t; } int fn(){ int ix=6, iy=7, ia=3, ib=5; swap(ix, iy); //产生函数定义体 swap(ia, ib); //不产生函数定义体 //... }
03:40:22 7
数据形参分: 引用型参数(提倡用本项) 非引用型参数 引用型参数分: 引用型参数 常量引用型参数
03:40:22
8
常量引用型形参
其数据形参可以是临时对象,所以,通过显式转换可以 规定模板的产生形式.但是,不能被隐式转换的数 据形参,其显式模板类型指定失效:
template<typename T> T const& max(T const& a, T const& b){ return a < b ? b : a; } int main(){ int ia=3; double db=6.7; db = max<double>(ia, db); db = max(static_cast<double>(ia), db); db = max<double>(&ia, db); //error }
03:40:22 16
高级模板概念中,类模板声明,如: Template<typename T>class List 等同于带有形式类型参数的模板类,如: List<T> 并将其作为一种类型看待 所以本质上不区分类模板与模板类.
03:40:22
17
模板类的使用将直接透入对象的构造,因此, 允许模板类带有值参便理所当然了. template<unsigned int N> class bitset; 但是类型值参将导致不同的类模板描述,因 而决定了不同的值参值,生成不同的模板类 bitset<100> a; bitset<200> b; a = b; // error 值参值应为编译能识别的常量,值参多为整 型.
03:40:22 6
2. 函数模板参数 ( Function Template Parameter )
数据参数是按值的性质匹配的,所以相容 类型之间可以转换 类型参数是按名字匹配的,更为苛刻
template<typename T> void swap(T& a, T& b){ T t=a; a=b; b=t; } int add(double a, double b){ return a+b; } int fn(){ int ia=3; double db=5.0; char s1[]="good", s2[]="better"; int x = add(ia, db); // ok swap(ia, db); // error swap(s1, s2); // error }