模板
[TOC]
三、模板
1.为什么要引入模板?
使用模板的目的就是能够让程序员编写与类型无关的代码。
2.关键字:
template
typename
class
3.函数模板的格式:
template <class 形参名, class 形参名, ...> 返回类型 函数名(参数列表)
{
// 函数体
}
1.函数模板
template
// max.cpp
template <class T> // 参数T表明是一种类型
T max(T a, T b) { // 函数模板
return (a > b) ? a : b;
}
// main.cpp
// 只写函数模板,不写模板函数,系统是不会产生任何代码数据的
int main() {
int iVal = max(100, 99);// 模板函数,无尖括号,默认类型为int
char cVal = max<char>('A', 'B');// 模板函数,有尖括号<char>,指定类型
return 0;
}
typename
// swap.cpp
// 通过typename定义模板
template <typename T>
void swap(T& a, T& b) {
T tmp = a;
a = b;
b = tmp;
}
// main.cpp
int main() {
int x = 20;
int y = 30;
swap<int>(x, y);
return 0;
}
变量作为模板参数
// display.cpp
// 变量作为模板的参数
template <int size>
void display() {
cout << size << endl;
}
// main.cpp
int main() {
display<10>(); // 模板参数需传入一个确定的值
return 0;
}
多参数函数模板
// display.cpp
// 多参函数模板
template <typename T, typename P>
void display(T a, P b) {
cout << a << "," << b << endl;
}
// main.cpp
int main() {
int a = 1024;
string str = "Hello, world!";
display<int, string>(a, str); // 使用的时候两个参数的类型都要指定出来
return 0;
}
typename和class混用
// minus.cpp
// 分清模板的参数和函数的参数,二者没有关系
template <typename T, class C>
T minus(T* a, U b);
// display.cpp
template <typename T, int size>
void display(T a) {
for(int i = 0; i < size; i++)
cout << a <<endl;
}
// main.cpp
int main() {
display<int, 5>(15);
return 0;
}
函数模板与重载
// display.cpp
// 三个不同的模板函数之间形成了重载
template <typename T>
void display(T a);
template <typename T>
void display(T a, T b);
template <typename T, int size>
void display(T a);
// main.cpp
int main() {
display<int>(10);
display<int>(10, 20);
display<int, 5>(30);
}
2.类模板
// MyArray.cpp
template <class T>
class MyArray {
public:
void display() { //在类内定义成员函数
...
}
private:
T *m_pArr;
};
// 在类外定义成员函数
template <class T>
void MyArray<T>::display() {
...
}
// main.cpp
int main() {
MyArray<int> arr; // 此时产生模板类
arr.display();
return 0;
}
多参数类模板
// Container.cpp
template <typename T, int iSize>
class Container {
public:
void display(); // 类内定义成员函数
private:
T m_obj;
};
// 类外定义成员函数
template <typename T, int iSize>
void Container<T, iSize>::display() {
for(int i = 0; i < iSize, i++)
cout << m_obj << endl;
}
// main.cpp
int main() {
Container<int, 10> ctn; // 此时产生模板类
ctn.display();
return 0;
}
特别提醒:模板代码不能分离编译
- 即声明和定义都必须写在.hpp文件中。
3.标准模板库
vector:向量
vector | 常用函数 |
---|---|
empty() | 判断向量是否为空 |
begin() | 返回向量迭代器首元素 |
end() | 返回向量迭代器末元素的下一个元素 |
clear() | 清空向量 |
front() | 第一个数据 |
back() | 最后一个数据 |
size() | 获得向量中数据 |
push_back(elem) | 将数据插入向量尾 |
pop_back() | 删除向量尾部 |
...... | ...... |
// main.cpp
int main() {
vector<int> iVec;
iVec.push_back(10);
iVec.push_pop();
cout << iVec.size() << endl;
return 0;
}
迭代器:iterator
- 是一个类
// main.cpp
int main() {
vector vec;
vec.push_back("hello");
vector<string>::iterator cIter = vec.begin();
for(; cIter != vec.end(); cIter++)
cout << *cIter << endl;
return 0;
}
list:链表
map:映射
map<int, string> m;
pair<int, string> p1(10, "shanghai");
pair<int, string> p2(20, "beijing");
m.insert(p1);
m.insert(p2);
cout << m[10] << endl;
cout << m[20] << endl;
map<string, string> m;
pair<string, string> p1("S", "shanghai");
pair<string, string> p2("B", "beijing");
m.insert(p1);
m.insert(p2);
cout << m["S"] << endl;
cout << m["B"] << endl;