Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 14 Templates.

Similar presentations


Presentation on theme: "Chapter 14 Templates."— Presentation transcript:

1 Chapter 14 Templates

2 OBJECTIVES To use function templates to conveniently create a group of related (overloaded) functions. To distinguish between function templates and function-template specializations. To use class templates to create a group of related types. To distinguish between class templates and class-template specializations. To overload function templates. To understand the relationships among templates, friends, inheritance and static members.

3 Topics 14.1 Introduction 14.2 Function Templates
14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

4 14.1 Introduction Motivation
2018年12月1日11时8分 14.1 Introduction Motivation 实现支持不同数据类型的取最大值函数(例:支持int、double、HugeInt等) 实现支持不同数据类型的Array类(例:支持int、double、HugeInt等)

5 2018年12月1日11时8分 14.1 Introduction 模板(template): 利用一种完全通用的方法来设 计函数或类而不必预先说明将被使用的每个对象 的类型,利用模板功能可以构造相关的函数或类 的系列,因此模板也可称为参数化的类型。—— 泛型编程(Generic Programming) 在C++语言中,模板可分为类模板(class template)和函数模板(function template)。

6 Topics 14.1 Introduction 14.2 Function Templates
14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

7 14.2 Function Templates -- review
定义模板: template关键字+尖括号<>括起来的template parameter list(模板参数列表) 模板参数列表: 参数称为formal type parameter(形式类型参数)。 在函数调用时替换为基本数据类型或用户自定义数据 类型。 每个参数都必须以关键词typename (或class )起 头,参数和参数之间必须以逗号分隔,如 template < typename T, typename V>

8 14.2 Function Templates -- review
template < typename T > // or template< classT > T maximum( T value1, T value2, T value3 ) { T maximumValue = value1; // assume value1 is maximum // determine whether value2 is greater than maximumValue if ( value2 > maximumValue ) maximumValue = value2; // determine whether value3 is greater than maximumValue if ( value3 > maximumValue ) maximumValue = value3; return maximumValue; } // end function template maximum

9 14.2 Function Templates -- review
template < typename T > // or template< classT > //模板声明 T maximum( T value1, T value2, T value3 ) //函数模板定义 { T maximumValue = value1; // assume value1 is maximum // determine whether value2 is greater than maximumValue if ( value2 > maximumValue ) maximumValue = value2; // determine whether value3 is greater than maximumValue if ( value3 > maximumValue ) maximumValue = value3; return maximumValue; } // end function template maximum T指定函数返回值、形参以及局部变量的类型 函数调用形式: maximum (1, 2, 3); maximum (int1, int2, int3);

10 14.2 Function Templates -- 定义
template< typename T > or template< class ElementType > template< typename BorderType, typename FillType > class,typename(关键字):函数模板类型参数,任何内部类型或用户自定义类型。

11 14.2 Function Templates -- 定义
2018年12月1日11时8分 14.2 Function Templates 定义 template <类型形参表>   返回值类型 函数名(形参表)   {   //函数定义体   } <类型形参表>可以有一到若干个类型形参,各形参前需要加上typename/class关键字,表示传递类型,当有多个形参时,各形参间用逗号分隔。 <类型形参表>中的每个形参表示一种数据类型。函数模板“形参表”中至少有一个形参的类型必须用<类型形参表>中的形参来定义。 函数模板只是说明,不能直接执行,需要特化为模板函数后才能执行。 May not include all type para?

12 如果是用户自定义类型,必须要对<<运算符进行重载
函数模板的参数T必须在模板头中声明 如果是用户自定义类型,必须要对<<运算符进行重载

13 Creates a function-template specialization of printArray where int replaces T
Creates a function-template specialization of printArray where double replaces T Creates a function-template specialization of printArray where char replaces T

14 14.2 Function Templates -- 函数处理过程
2018年12月1日11时8分 14.2 Function Templates 函数处理过程 在程序中说明了一个函数模板 编译系统发现有一个相应的函数调用 例如:printArray( a, ACOUNT ); 编译器寻找和使用最符合函数名和参数类型的函数调用 根据实参中的类型来确认是否匹配函数模板中对应的形参,然后生成一个模板函数(函数模板特化)。(该模板函数的定义体与函数模板的函数定义体相同) 例如:对于int类型的模板特化: void printArray( const int *array, int count ) { for ( int i = 0; i < count; i++ ) cout << array[ i ] << " "; cout << endl; } 编译这个新建的函数 What’s Template function ? void printArray( const int *, int ); void printArray( const double *, int ); void printArray( const char *, int );

15 Topics 14.1 Introduction 14.2 Function Templates
14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

16 14.3 Overloading Function Templates
2018年12月1日11时8分 14.3 Overloading Function Templates 函数模板可以被重载 允许有其它同名的函数模板,但参数不同 允许有其它同名的函数,但参数不同 编译器挑选最佳匹配的函数或模板 编译器通过匹配过程确定调用哪个函数。 首先,编译器寻找和使用最符合函数名和参数类型的函数调用。如果找不到,则检查是否可以用函数模板产生符合函数名和参数类型的模板函数。 如果有多个函数和调用函数相匹配(且匹配程度相同),编译器会认为有二义性,将产生编译错误 如果没有找到符合函数,将考虑调用强制类型转换

17 #include <iostream> using namespace std;
2018年12月1日11时8分 #include <iostream> using namespace std; template <class T> void print (const T &a, int b) {cout << "first function called!"<< endl;} template <class T, class T1> void print (const T &a, T1 b) {cout << "second function called!";} void print (const T &a, int c, T1 b) {cout << " third function called!";} void print (const T &a, T1 b, int c) {cout << “fourth function called!";} void print (int a, int b) {cout << " fifth function called!"<< endl;} void print (int a ) {cout << “sixthfunction called!"<< endl;} print(1,2); print(1.1, 2); print(1,2,3);

18 Topics 14.1 Introduction 14.2 Function Templates
14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

19 14.4 Class Templates --定义 1、类模板通过允许将泛型类实例化为明确类 型的类来实现软件复用
2、类是对问题空间的抽象,而类模板则是对 类的抽象,即更高层次上的抽象。 3、程序中可以首先定义一个类模板,然后通 过使用不同的实参生成不同的类。 4、类模板的定义格式: template <typename <类型参数>> //模板声明 class <类名> // 类定义 { …… };

20 14.4 Class Templates 定义 每个“类型形参”前必须加typename or class关键字,对类模板进行实例化时,代表某种数据类型;也可以是普通数据类型形参,实例化时代表具体数据 例如: template < typename arg1, int arg2, typename arg3> class myclass   { arg1 buffer[arg2]; arg3 x;  //类的定义体   }; template <类型形参表> class “类模板名” {   private:   私有成员定义   protected:   保护成员定义   public:   公有成员定义 }; 类模板中成员函数可以放在类模板的定义体中(此时与类中的成员函数的定义方法一致)定义,也可以放在类模板的外部来定义,格式为: template <类型形参表> 函数返回类型 类模板名<类型名表>::成员函数(形参) template < typename arg1, int arg2, typename arg3> void myclass<arg1,arg2,arg3>::print() {}

21 14.4 Class Templates --定义 类模板定义只是对类的描述,它本身还不是一个实实在在的类。
类模板不能直接使用,必须先特化(specialized)为相应的模板类,定义模板类的对象(即实例)后,才可使用(创建对象等)。 可以用以下方式创建类模板的特化及对象。 类模板名<类型实参表> 对象名表; 如:Myclass<int> a; 此处的<类型实参表>要与该模板中的<类型形参表>匹配,要具有同样的顺序和类型,否则会产生错误!

22 例: 定义一个任意类类型AnyType #include <iostream> using namespace std;
template <typename T> class AnyType { T x, y; public: AnyType(T a, T b): x(a), y(b){} T GetX(){return x;} T GetY(){return y;} };

23 // 测试函数 int main() { AnyType <int> i (1, 2);
AnyType <double> d (1.5, 2.7); AnyType <char> c ('a', 'b'); AnyType <char *> s ("Hello", "template class"); cout << "整型类:" << i.GetX() << ", " << i.GetY() << endl; cout << "双精度类:" << d.GetX() << ", " << d.GetY() << endl; cout << "字符类:" << c.GetX() << ", " << c.GetY() << endl; cout << "字符串类:" << s.GetX() << ", " << s.GetY() << endl; return 0; }

24 14.4 Class Templates --应用 栈:先进后出 数据结构: 操作: 需求:建立栈的类模板,满足不同类型的元素?
size:栈的大小 top: 栈顶位置,初始值为-1(空栈) stackPtr :存储栈中元素的一组连续存储空间 操作: push:如果栈不满,则向栈中增加一个元素,top增1 pop: 如果栈不空,则从栈中弹出一个元素,top减1 isEmpty:如果top为-1,则栈为空 isFull:如果top为size-1,则栈满 需求:建立栈的类模板,满足不同类型的元素?

25 Outline Stack.h (1 of 3) 创建类模板 Stack,包含类型参数 T 成员函数在参数列表中使用类型参数T

26 Outline (2 of 3) Stack.h Data member stackPtr is a pointer to a T
在类模板之外定义成员函数,必须以模板头(template header)开始

27 Outline (3 of 3) Stack.h template <类型形参表>
函数返回类型 类模板名<类型名表>::成员函数(形参)

28 Outline fig14_03.cpp (1 of 3) Create class-template specialization Stack< double > where type double is associated with type parameter T

29 Create class-template specialization Stack< int > where type int is associated with type parameter T

30 Outline (3 of 3) fig14_03.cpp 思考:stack类模板如果要处理用户自定义类性,需要用户自定义类型提供什么函数?
2018年12月1日11时8分 Outline fig14_03.cpp (3 of 3) 思考:stack类模板如果要处理用户自定义类性,需要用户自定义类型提供什么函数? 重载赋值运算符,重载数组下标运算符 如何避免main函数中重复的逻辑?使用函数模板

31 创建函数模板来测试类模板Stack<T>
Outline 创建函数模板来测试类模板Stack<T> fig14_04.cpp (1 of 3) Use a function template to process Stack class-template specializations

32 Outline fig14_04.cpp (2 of 3)

33 2018年12月1日11时8分 Outline fig14_04.cpp (3 of 3)

34 Topics 14.1 Introduction 14.2 Function Templates
14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

35 2018年12月1日11时8分 14.5 Nontype Parameters and Default Types for Class Templates(非类型参数和类模板的缺省类型) 非类型的模板形参 特化时作为常量对待 可以有缺省参数 Example Template header: template< typename T, int elements = 10 > Declaration: Stack< double, 100 > salesFigures; 类型形参也可以有默认实参 Template header: template< typename T = string > Declaration: Stack<> jobDescriptions;

36 先特化再创建对象 定义一个能表示不同大小的栈模板 在编译时指定一个容器类的大小,可以消除使用new的开销以及风险
template <typename T, int size> bool Stack <T,size>::push(const T &x) { if ( !isFull() ) { buffer[ ++top ] = x; return true; } return false; bool Stack <T,size>::pop(T &x) {if ( !isEmpty() ) x = buffer[ top-- ]; Stack <int,100> st1; Stack <double,200> st2; template <typename T, int size> class Stack { T buffer[size]; int top; int tip; public: Stack() {top=-1;} bool push(const T &x); bool pop(T &x); bool isEmpty() const { return top == -1; } bool isFull() const return top == size - 1; }; 先特化再创建对象 在编译时指定一个容器类的大小,可以消除使用new的开销以及风险

37 14.5 Nontype Parameters and Default Types for Class Templates(无类型参数和类模板的缺省类型)
Explicit specializations(显式特化) 当某一特殊数据类型不能使用通用类模板时,可以定制处理(即:重定义该类型的类模板。) 显式特化: Stack< Employee > specialization template<> class Stack< Employee > { … }; 完全代替了通用类模板 Stack< Employee > 没有使用原来类模板的任何内容,甚至可以包含不同的成员 优点:可以兼容已有的基于模板的操作

38 Topics 14.1 Introduction 14.2 Function Templates
14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.8 Notes on Templates and static Members

39 14.6 Notes on Templates and Friends
2018年12月1日11时8分 14.6 Notes on Templates and Friends Assume class template X with type parameter T as in: template< typename T > class X 函数声明为类模板的每一个特化的友元 friend void f1();//无参数 f1 is a friend of X< double >, X< string >, etc. 函数声明为类模板的某一类型参数特化的友元 friend void f2( X< T > & );//带参数 f2( X< float > & ) is a friend of X< float > but not a friend of X< string > 关于模板+友元存在的问题:

40 template <typenameT, int size>
class Stack; template <typename Type, int size2> ostream& operator << (ostream &out, Stack<Type,size2>& s) { Type elem; while (!s.isEmpty()) { s.pop(elem); out<<elem<<endl; } return out; template < typenameT, int size> class Stack { friend ostream& operator << (ostream &out, Stack<T,size>& s); T buffer[size]; int top; int tip; public: Stack() {top=-1;} bool push(const T &x); bool pop(T &x); bool isEmpty() const { return top == -1; } bool isFull() const return top == size - 1; } }; template <class T, int size> bool Stack <T,size>::push(const T &x) { if ( !isFull() ) { buffer[ ++top ] = x; return true; } return false; } bool Stack <T,size>::pop(T &x) {if ( !isEmpty() ) { x = buffer[ top-- ]; return true; } return false; } // 测试函数 int main() Stack <int,100> st1; for (int i=0; i<=10;i++) { st1.push(i*10); cout<<st1; Stack <double,200> st2; return 0;

41 14.6 Notes on Templates and Friends
另一个类的成员函数可以声明为类模板每一个特化的友元(无参数) friend void A::f3(); f3 of class A is a friend of X< double >, X< string >, etc. 另一个类的成员函数可以声明为类模板某个类型参数特化的友元(带参数) friend void C< T >::f4( X< T > & ); C< float >::f4( X< float > & ) is a friend of X< float > but not a friend of X< string >

42 14.6 Notes on Templates and Friends
另一个类可以声明为类模板的每一个特化的友元 friend class Y; (无类型参数) Every member function of class Y is a friend of X< double >, X< string >, etc. 另一个类可以声明为类模板的某个类型参数特化的友元 friend class Z< T >; (有类型参数) Class-template specialization Z< float > is a friend of X< float >, Z< string > is a friend of X< string >, etc.

43 模版类的友元函数 友元类 template<typename T> template<class T>
class linkedStack; template <typename T> class Node { friend linkedStack<T>; private: T data; Node<T> *link; //指向下一个 }; template < typename T> ostream& operator << (ostream &out, linkedStack<T > &s) { T elem; while (!s.IsEmpty()) { s.Delete(elem); out<<elem<<endl; } return out; template<class T> class linkedStack { friend ostream& operator << (ostream &, linkedStack<T>&); public: linkedStack () { top = 0; } ~linkedStack(); bool IsEmpty() const { return top == NULL; } linkedStack<T> & Add(const T&x); linkedStack<T> & Delete (T &x); private: Node<T> *top; }; 模版类的友元函数 友元类

44 template<class T>
linkedStack<T>::~linkedStack() { Node<T> *next; while (top != 0) { next = top->link; delete top; top = next; } linkedStack<T> &linkedStack<T>::Add(const T&x) { Node<T> *p = new Node<T>; p->data = x; p->link = top; top = p; return *this; template<class T> linkedStack<T> &linkedStack<T>::Delete(T &x) { Node<T> *tempp = NULL; x = top->data; tempp = top->link; delete top; top = tempp; return *this; } int main() {linkedStack<int> LS; for (int i=0; i<=10;i++) { LS.Add(i*10); cout<<LS; return 0;

45 Topics 14.1 Introduction 14.2 Function Templates
14.3 Overloading Function Templates 14.4 Class Templates 14.5 Nontype Parameters and Default Types for Class Templates 14.6 Notes on Templates and Friends 14.7 Notes on Templates and static Members

46 14.7 Notes on Templates and static Members
Each class-template specialization gets its own copy of the class template’s static member functions template <typename T> class A { static int x; }; template < typename T> int A<T>::x=0; A<int> a1,a2; // a1和a2共享一个x A<double> b1,b2; // b1和b2共享一个x

47 模板和继承的使用区别 当对象的类型不影响类中函数的行为时,就要使用模板来生成这样一组类。
当对象的类型影响类中函数的行为时,就要使用继承来得到这样一组类。

48 模板编译的问题 使用接口和实现分离的形式

49 9.4 Separating Interface from Implementation --隐藏类的源代码
类实现(成员函数定义) 类定义(接口) 类客户代码 A.cpp A.h Main.cpp 编译 编译 修改类实现代码 A.obj Main.obj 链接 EXE

50 模板编译的问题 错误分析: 结论:把模板的定义和实现都放到头文件中
Main.cpp 在编译目标文件是成功的,在链接的时候出现了错误。显示找不到RecT<int>类的方法。 因为其中的T类型在使用前还未知类型,如何分配内存还无法确定,因此 Rect.cpp无法独立生成目标文件。 编译模板类不能分两步走。模板类的实现文件需要和使用类的程序一起编译,编译器知道程序需要使用何种类后才可以编译出相应的类来。 结论:把模板的定义和实现都放到头文件中

51 Summary 函数模板和函数模板重载 类模板 定义 类型参数和非类型参数 实例创建 模板和继承 模板和友元 模板中的静态成员

52 Homework! 实验必选题目(交实验报告): 14.7, 14.8

53 14.11 What is the relationship between function templates and overloading?
函数模板与重载密切相关:(3分) 函数模板特化之间是重载关系 函数模板之间可以重载 函数模板与普通函数之间可以重载 函数模板与重载的区别:(2分) 重载是程序员编程时设计多个具有相同函数名、不同参数的函数 函数模板是在编译时,由编译器生成多个具有相同函数名、不同参数的函数模板特化

54 Template<typename T> class Ct1 {
习题14.20 Template<typename T> class Ct1 { friend void f1(); friend void f2(Ct1<T> &); //f2(Ct1<int> &) friend void Ct2::f3(); friend void Ct3<T>::f4(Ct1<T> &) //Ct3<int>::f4(Ct1<int> &) friend class C4; friend class Ct5<T>; //Ct5<> }


Download ppt "Chapter 14 Templates."

Similar presentations


Ads by Google