模板
背景
多个重载的函数的同步的问题:
其解决问题的逻辑是一致的、函数体语句相同,只是处理的数据类型不同
- 重复劳动:冗余性
- 改动的危险:不一致性。
从而让我们把模板构建的核心放在算法实现上。
函数模板定义语法
只需在相应函数定义之前加:
template<param type-table>
然后在函数体中的相应位置使用模板的参数类表中的抽象类型即可。
参数类表的构成
参数类不仅可由抽象的类型参数组成,还可以使用抽象常量类型、模板类型等。
- 类型参数:class(或typename)标识符
- 常量参数:类型说明符 标识符
- 模板参数:template <参数表> class标识符
模板使用条件( )
一个函数模板并非自动可以处理所有类型的数据
只有能够进行函数模板中运算的类型,可以作为类型实参
所以,自定义的类,需要重载模板中的运算符,才能作为类型实参
这也就是FLTK lab中无法构建Circle类对象的原因。
类模板
类模板的声明是函数模板和类的定义语法的嵌合。仅需在出现类名时用 [classname]<T>
代替。
扫描二维码关注公众号,回复:
11168579 查看本文章
例如
//#include <iostream>
// #include <cstdlib>
// using namespace std;
/* struct Student {
int id; //学号
float gpa; //平均分
}; */
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) { }
template <class T>
T &Store<T>::getElem() {
//如试图提取未初始化的数据,则终止程序
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
}
/*int main() {
Store<int> s1, s2;
s1.putElem(3);
s2.putElem(-7);
cout << s1.getElem() << " " << s2.getElem() << endl;
Student g = { 1000, 23 };
Store<Student> s3;
s3.putElem(g);
cout << "The student id is " << s3.getElem().id << endl;
Store<double> d;
cout << "Retrieving object D... ";
cout << d.getElem() << endl;
//d未初始化,执行函数D.getElement()时导致程序终止
return 0;
} */
特别注意,#include <cstdlib>
必须要有!
群体与类模板实例
群体是多个数据元素的集合。
其中元素按位置排列有序的群体叫做线性群体,元素次序和逻辑关系相对应。
非线性群体不用位置来标识元素。例如:二叉树,这也正是我们在map
中不能使用迭代器的原因。
数组类模板
详见vector章。