清华大学C++课件-第六讲 函数模板与类模板_35310879
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态数组类模板
动态数组类模板程序
//重载下标运算符,实现与普通数组一样通过下标访问元素,并且具有越界检查功能 template <class T> T &Array<T>::operator[] (int n) { assert(n >= 0 && n < size); //检查下标是否越界 return list[n]; //返回下标为n的数组元素 } 针对常对象定 template <class T> const T &Array<T>::operator[] (int n) const 义常函数 { assert(n >= 0 && n < size); //检查下标是否越界 return list[n]; //返回下标为n的数组元素 } //重载指针转换运算符,将Array类的对象名转换为T类型的指针 template <class T> Array<T>::operator T * () { return list; //返回当前对象中私有数组的首地址 }
函数模板
函数模板的示例
int main() //主函数 { const int A_COUNT = 8, B_COUNT = 8, C_COUNT = 20; int a[A_COUNT] = { 1, 2, 3, 4, 5, 6, 7, 8 }; //定义int数组 double b[B_COUNT] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 };//定义double数组 char c[C_COUNT] = "Welcome to see you! ";//定义 char数组 cout << " a array contains:" << endl; outputArray(a, A_COUNT); //调用函数模板 cout << " b array contains:" << endl; outputArray(b, B_COUNT); //调用函数模板 cout << " c array contains:" << endl; outputArray(c, C_COUNT); //调用函数模板 return 0; }
函数模板实例
运行结果: 5 5.5
函数模板
求绝对值函数的模板分析
编译器从调用abs()时实参的类型,推导出函数 模板的类型参数。例如,对于调用表达式abs(n), 由于实参n为int型,所以推导出模板中类型参数 T为int 当类型参数的含义确定后,编译器将以函数模 板为样板,生成一个函数:
int abs(int x) { return x < 0 ? –x : x; }
类模板
类模板的声明
类模板:
template <模板参数表> class 类名 {类成员声明}
与函数模板中的“模 板参数表”完全一样
如果需要在类模板以外定义其成员函数, 则要采用以下的形式:
template <模板参数表> 类型名 类名<模板参数标识符列表>::函数名(参数表)
类模板
#include <iostream> #include <cstdlib> using namespace std; // 结构体Student struct Student { int id; float gpa; };
类模板
类模板应用举例
template <class T> //提取数据函数的实现 注意,函数模板中 T &Store<T>::getElem() 无法对参数化类型T { //如试图提取未初始化的数据,则终止程序 进行“与具体类型 相关的”处理。 if (!haveValue) { cout << "No item present!" << endl; exit(1); //使程序完全退出,返回到操作系统。 } return item; // 返回item中存放的数据 } template <class T> //存入数据函数的实现 void Store<T>::putElem(const T &x) { // 将haveValue 置为true,表示item中已存入数值 haveValue = true; item = x; // 将x值存入item }
等效原则: Student g = { 1000, 23 }; “Store<Student>” Store<Student> s3; 相当于一个类名 s3.putElem(g); cout << "The student id is " << s3.getElem().id << endl; 等效原则: Store<double> d; “Store<double>” cout << "Retrieving object D... "; 相当于一个类名 cout << d.getElem() << endl; //由于d未经初始化,在执行函数D.getElement()过程中导致程序终止 return 0; }
函数模板
#include <iostream> using namespace std; template <class T> void outputArray(const { for (int i = 0; cout << cout << endl; }
函数模板的示例
//定义函数模板 T *array, int count) i < count; i++) array[i] << " ";
函数模板
函数模板的示例
运行结果如下: a array contains: 1 2 3 4 5 6 7 8 b array contains: 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 c array contains: W e l c o m e t o s e e y o u !
类模板应用举例
//学号 //平均分
类模板
类模板应用举例
//类模板:实现对任意类型数据进行存取 template <class T> class Store { private: T item; // item用于存放任意类型的数据 bool haveValue; // haveValue标记item是否已被存 入内容 public: Store(); // 缺省形式(无形参)的构造函数 T &getElem(); //提取数据函数 void putElem(const T &x); //存入数据函数 }; //以下实现各成员函数。 template <class T> //缺省构造函数的实现 Store<T>::Store(): haveValue(false) { } Store<T>表示类型 参数实例化之后的 Store模板,相当于 类名。
函数模板与类模板Biblioteka
函数模板 类模板 动态数组类模板 链表类模板 栈类模板 队列类模板 综合实例 模板的实例化机制 模板的特化 模板元编程简介
类模板
类模板概述
类模板的作用
使用类模板使用户可以为类声明一种模式,使 得类中的某些数据成员、某些成员函数的参数、 某些成员函数的返回值,能取任意类型(包括 基本类型和用户自定义类型)
采用深拷贝,会调用类型T的赋 值函数。(思考:为什么不是拷 贝构造函数?)
动态数组类模板
动态数组类模板程序
//重载"="运算符,将对象rhs赋值给本对象。实现对象之间的整体赋值 template <class T> 注意对函数 Array<T> &Array<T>::operator = (const Array<T>& rhs) 头的理解 { //如果本对象中数组大小与rhs不同,则删除数组原有内存,然后重新分配 if (&rhs != this) 注意,赋值函数必须判 { 断是否为自赋值(因为 if (size != rhs.size) 可能出现间接的自赋值) { delete [] list; //删除数组原有内存 size = rhs.size; //设置本对象的数组大小 list = new T[size]; //重新分配n个元素的内存 } //从对象X复制数组元素到本对象 for (int i = 0; i < size; i++) 采用深拷贝,会调用类 list[i] = rhs.list[i]; 型T的赋值函数。 } return *this; //返回当前对象的引用 } 为了实现链式表达,应该返回当前对象的引 用。(思考:能否返回this?能否返回rhs?)
template <模板参数表>
函数定义
模板参数表的内容
类型参数:class(或typename) 标识符
常量参数:类型说明符 标识符 模板参数:template <参数表> class 标识符
函数模板
#include <iostream> using namespace std; template<typename T> T abs(T x) { return x < 0? -x : x; } int main() { int n = -5; double d = -5.5; cout << abs(n) << endl; cout << abs(d) << endl; return 0; }
类模板
int main() { Store<int> s1, s2; s1.putElem(3); s2.putElem(-7); cout << s1.getElem() << "
类模板应用举例
等效原则: “Store<int>”相当 于一个类名
" << s2.getElem() << endl;
第六讲 函数模板与类模板
函数模板与类模板
函数模板 类模板 动态数组类模板 链表类模板 栈类模板 队列类模板 综合实例 模板的实例化机制 模板的特化 模板元编程简介
函数模板
函数模板概述
函数模板可以用来创建一个通用功能的函数, 以支持多种不同形参,进一步简化重载函数的 函数体设计 定义方法:
Array<T>表示类型 参数实例化之后的 Array模板,相当于 类名。
T作为类型参数,在 模板的定义中可以 当作类名使用。
template <class T> //数组类模板定义 class Array { private: T* list; //用于存放动态分配的数组内存首地址 int size; //数组大小(元素个数) public: Array(int sz = 50); //构造函数 赋值函数(即拷 Array(const Array<T> &a); //拷贝构造函数 贝函数) ~Array(); //析构函数 Array<T> & operator = (const Array<T> &rhs); //重载"=“ T & operator [] (int i); //重载"[]” 针对常对象定 const T & operator [] (int i) const; 义常函数 operator T * (); //重载到T*类型的转换 operator const T * () const; 针对常对象定 int getSize() const; //取数组的大小 义常函数 void resize(int sz); //修改数组的大小 }; 类型转换重载:在类体中通过指定关键字operator,并在其后加上转换的目标类型后, 就可以声明转换函数。转换函数必须是成员函数,它的声明不能指定返回类型和参数表。
函数模板与类模板
函数模板 类模板 动态数组类模板 链表类模板 栈类模板 队列类模板 综合实例 模板的实例化机制 模板的特化 模板元编程简介
动态数组类模板
#ifndef ARRAY_H #define ARRAY_H #include <cassert>
动态数组类模板程序
动态数组类模板
动态数组类模板程序
template <class T> Array<T>::Array(int sz) //构造函数 { assert(sz >= 0);//sz为数组大小(元素个数),应当非负 size = sz; // 将元素个数赋值给变量size list = new T [size]; //动态分配size个T类型的元素空间 } template <class T> Array<T>::~Array() //析构函数 针对每个元素 { 都会调用T的 delete [] list; 缺省构造函数 } //拷贝构造函数 template <class T> Array<T>::Array(const Array<T> &a) { size = a.size; //从对象x取得数组大小,并赋值给当前对象的成员 //为对象申请内存并进行出错检查 list = new T[size]; // 动态分配n个T类型的元素空间 for (int i = 0; i < size; i++) //从对象X复制数组元素到本对象 list[i] = a.list[i]; }