函数模板( Function templates)
模板(Templates)使得我们可以生成通用的函数,这些函数能够接受任意数据类型的参数,可返回任意类型的值,而不需要对所有可能的数据类型进行函数重载。这在一定程度上实现了宏(macro)的作用。它们的原型定义可以是下面两种中的任何一个:
template <typename identifier> function_declaration;
template <class identifier> function_declaration;
上面两种原型定义的不同之处在关键字class 或 typename的使用。它们实际是完全等价的,因为两种表达的意思和执行都一模一样。
在函数中使用模板typename
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
template <typename Tx> //这一句的作用就是定义Tx参数类型,根据传入的数据类型确定
void insertsort(vector<Tx> &numbers){//插入排序
int numlen=numbers.size();
int flag;
Tx temp;
for (int i=1;i<numlen;i++){
temp=numbers[i];
for (flag=i;flag>0&&numbers[flag-1] > temp;flag--)
numbers[flag]=numbers[flag-1];
numbers[flag] = temp;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[]={9,8,7,6,5,4,3,2,1};
char b[]={'j','f','e','d','c','b','a'};
vector<int> numbers(a,a+9);
vector<char> character(b,b+7);
insertsort(numbers);
insertsort(character);
for (int i=0;i<character.size();i++)
cout<<character[i]<<" ";
cout<<endl;
system("pause");
}
以上代码为插入排序的函数实现,输入有两种格式一种是int型,一种为char型。通过template < typename Tx> 来确定传入参数
输出结果均已排好序。
在函数中使用模板class
#include "stdafx.h"
#include <iostream>
template <class Ty> Ty getMin (Ty a, Ty b) {
Ty res;
res = a<b ? a : b;
return res;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[2]={123,321};
char b[2]={'g','p'};
int numMin=getMin(a[0],a[1]);//传入为int
char charMin=getMin(b[0],b[1]);//传入为char
cout<<numMin<<endl<<charMin<<endl;
system("pause");
}
在这个样例中,a、b、res都为Ty型, 即在class模板声明时在class 后边所接的Ty参数
3. 在类中使用模板
我们也可以定义类模板(class templates),使得一个类可以有基于通用类型的成员,而不需要在类生成的时候定义具体的数据类型,例如:
//test.h
#include <iostream>
#include <vector>
#include <string>
template <class Tz>
class Stacks{
private:
std::vector<Tz> elems;
public:
void push_e(Tz const &in);
void pop_e();
Tz top_e();
bool empty_e() const{
return elems.empty();
}
};
template <class Tz>
void Stacks<Tz>::push_e(Tz const &in){
elems.push_back(in);
}
template <class Tz>
void Stacks<Tz>::pop_e(){
if (elems.empty()) throw out_of_range("Stack<>::pop(): empty stack");
elems.pop_back();
}
template <class Tz>
Tz Stacks<Tz>::top_e(){
if (elems.empty()) throw out_of_range("Stack<>::pop(): empty stack");
return elems.back();
}
//test.cpp
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
Stacks<std::string> string_elems;
Stacks<int> int_elems;
string_elems.push_e("Hello world");
int_elems.push_e(1001);
int_elems.push_e(1002);
cout<<int_elems.top_e()<<endl;
int_elems.pop_e();
cout<<int_elems.top_e()<<endl<<string_elems.top_e()<<endl;
system("pause");
}
运行结果如下:
在上述类模板的使用中定义了class Stacks
,类型为template <class Tz>
使用STL vector作为容器,存入不同类型的数据。
这个类实现了以下几个功能 pop(弹出最后一个元素)、push(在最后插入一个元素)、Isempty(判断容器是否为空)、top(返回最后一个元素)
如下是笔者在编写该段程序时遇到需要注意的点 :
void Stacks<Tz>::pop_e()
在写函数的定义时必须要在类的后边加上< Tz >模板参数,否则编译无法通过- 每个函数的定义前都需要加
template <class Tz>
注:
最近在搬砖的时候发现了如下一种模板的用法,
template <typename BaseType = QGraphicsItem >
这句也可以在github qdraw项目里找到,最后在《c+=11primer》中找到了这种用法,原文是这么写的——
如果是一个类模板为其所有模板参数都提供了默认实参,且我们希望使用这些默认实参。
template <class T = int >
//T默认为int