模板有什么用?
Template所代表的泛型编程是C++语言中的重要的组成部分。
实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。
函数模板并不缩短可执行程序,最终由编译器展开,最终的代码不包含任何模板,只含了为程序生成的实际函数。
STL中类似vector其实也是用模板类实现的。所以可以vectot vector
一、函数模板实例
template<typename T,typename T_2>
T calculate_temp(T cal_temp,T_2 cal_temp_2)
{
cout <<"size of cal_temp = "<< sizeof(cal_temp)<<endl;
cout <<"size of cal_temp_2 = "<< sizeof(cal_temp_2)<<endl;
return cal_temp*cal_temp_2;
}
int main(int arg,char** argv)
{
double c=10.235;
int a = 20;
cout << calculate_temp(c,a)<<endl;
return 0 ;
}
二、函数模板中class与typename 的区别?
下面展示一些 函数模板
。
template<class T>
T calculate_class(T cal_temp)
{
cout <<"size of cal_temp = "<< sizeof(cal_temp)<<endl;
return cal_temp*3;
}
template<typename T>
T calculate_typename(T cal_temp)
{
cout <<"size of cal_temp = "<< sizeof(cal_temp)<<endl;
return cal_temp*3;
}
他们的调用方式如下:
int c = 10;
calculate_class(c);
calculate_typename<int>(c);
区别就是:typename 修饰的模板在编译时,需要明确指定参数类型。
但实际情况是不指明参数类型一样可以使用,原因是不同编译器有不同的实现方式。
关于typename,是C++98引入的,之前都是使用class。
如果不考虑对向后兼容的问题,应使用typename而不是class。
三、类模板
类模板与函数模板无差,
与函数模板不同的是,类模板在实例化时必须显式地指明数据类型,编译器不能根据给定的数据推演出数据类型。
类外定义成员函数。在类外定义成员函数时仍然需要带上模板头,类名后面也要带上类型参数。
#include <iostream>
using namespace std;
template<class T1, class T2> //这里不能有分号
class Point{
public:
Point(T1 x, T2 y): m_x(x), m_y(y){ }
public:
T1 getX() const; //获取x坐标
void setX(T1 x); //设置x坐标
T2 getY() const; //获取y坐标
void setY(T2 y); //设置y坐标
private:
T1 m_x; //x坐标
T2 m_y; //y坐标
};
template<class T1, class T2> //模板头
T1 Point<T1, T2>::getX() const /*函数头*/ {
return m_x;
}
template<class T1, class T2>
void Point<T1, T2>::setX(T1 x){
m_x = x;
}
template<class T1, class T2>
T2 Point<T1, T2>::getY() const{
return m_y;
}
template<class T1, class T2>
void Point<T1, T2>::setY(T2 y){
m_y = y;
}
int main(){
Point<int, int> p1(10, 20);
cout<<"x="<<p1.getX()<<", y="<<p1.getY()<<endl;
Point<int, char*> p2(10, "东经180度");
cout<<"x="<<p2.getX()<<", y="<<p2.getY()<<endl;
//除了对象变量,我们也可以使用对象指针的方式来实例化:
Point<char*, char*> *p3 = new Point<char*, char*>("东经180度", "北纬210度");
cout<<"x="<<p3->getX()<<", y="<<p3->getY()<<endl;
return 0;
}
来自:http://c.biancheng.net/cpp/biancheng/view/2992.html
四、模板函数的指针
4.1 实例1:
模板函数insertionSort本身:
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
T e = arr[i];
int j; // j保存元素e应该插入的位置
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
参数列表中有函数指针的模板函数:
template<typename T>
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl;
}
模板函数insertionSort作为函数指针传参给testSort:
testSort("Insertion Sort", insertionSort,arr,n);
4.2 实例2:
下面这样是无法编译通过的。
template <class T> typedef void (*Action)(T)
模板函数insertionSort本身:
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
T e = arr[i];
int j; // j保存元素e应该插入的位置
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}
return;
}
参数列表中有函数指针的模板函数:
template<typename T>
struct Type
{
typedef void(*aaaaa)(T[], int);
};
void testSort(const string &sortName, Type<int>::aaaaa sort, int arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;
}
模板函数insertionSort作为函数指针传参给testSort:
testSort("Insertion Sort", insertionSort,arr,n);
参考
https://blog.csdn.net/u010632547/article/details/105634066
https://www.cnblogs.com/easyfrog/archive/2012/11/04/2753468.html