一、 模板
模板是泛型编程的基础,模板是创建泛型类 或 泛型函数的蓝图
1. 函数模板
1.1 当使用函数模板时,下方示例中的自定义函数Max( ) 可以比较任意类型的两个变量。代码不局限于某一类型,这种编写代码的方式被称为泛型编程,模板就是泛型编程的基础
1.2 示例是一个函数模板,作用是比较 T类型的两个变量 a b 的大小
template <typename T>
1.3 示例中的T const &Max( ) 说明 Max( )函数的返回值是一个T类型常量 T const 的引用 & ;后面的参数是T类型常量 a,b的引用。这样编码的好处:引用可以减少数值传递过程中的时间,const关键字保证传过来的值在使用时不被改变
1.4 引用 & 举例
int &reference=i; // reference 是 i的引用
i=3;
cout<<i<<' '<<reference<<endl; //print:3 3
1.5 T const & 与 T &的区别:前者是常引用,不能修改其值,后者为引用,可以修改值。当返回值是常引用时,不能把返回值作为左值
1.6 示例中用到了内联函数 inline,内联函数用空间换时间,但代码一般不会超过10行
#include <iostream>
using namespace std;
template <typename T> inline T const &Max(T const &a, T const &b) //inline可删除
{
return a < b ? b:a;
}
int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "xiaosi";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
2. 类模板
2.1 如下示例是向量 vector的套壳,实际意义一般,主要还是用来熟悉类模板的使用
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept> //throw out_of_range()
using namespace std;
template <class T> class Stack
{
private:
vector<T> vs; //容器vs的存储对象是T
public:
void push(T const &); // 入栈 ,语句等价于 void push(T const &elment);
void pop(); // 出栈
T top() const; // 返回栈顶元素T,但const的位置好玄啊?
/*
bool empty() const //empty()函数不存在也没关系
{
return vs.empty(); // 如果为空则返回真
} */
};
template <class T>
void Stack<T>::push (T const &elment)
{
vs.push_back(elment); // void push_back(const T& x):向量尾部增加一个元素X
}
template <class T>
void Stack<T>::pop ()
{
if (vs.empty()) // 返回True时为空
{
throw out_of_range("Stack<>::pop(): empty stack");
}
vs.pop_back(); // void pop_back():删除向量中最后一个元素
}
template <class T>
T Stack<T>::top () const
{
if (vs.empty()) // 返回True时为空
{
throw out_of_range("Stack<>::top(): empty stack");
}
return vs.back(); //reference back():返回尾元素的引用
}
int main()
{
try
{
Stack<int> intStack; // int 类型的栈
Stack<string> stringStack; // string 类型的栈
// 操作 int 类型的栈
intStack.push(3);
cout << intStack.top() <<endl;
// 操作 string 类型的栈
stringStack.push("ancient terrace");
cout << stringStack.top() << endl;
stringStack.pop();
//stringStack.pop();
stringStack.top();
}
catch (exception const& ex)
{
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}
3. 模板中的关键字 typename和class
3.1 C++ Template 会用到关键字 typename 和 class ,表面看起来 两者可以替换
3.2 class 用于定义类,在模板引入 C++ 后,最初定义模板的方法如下
template<class T>......
这里class表明T是一个类型,后面为了避免混淆,引入 typename 关键字,其作用和class一样表明后面的符号是一个类型
template<typename T>......
3.3 在模板定义语法中,关键字 class 与 typename 的作用完全一样