[STL]模板(类&函数)

模板

模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。
模版可以分为两类,一个是类模版,另一个是函数模版。

类模板

template<typename T1,typename T2 int len= 7>
class test{ 
private:
  T1  m_First;
  T2  m_Second;
  int m_cnt;
public:
  test(T1 first,T2 second,int c=len):m_First(first),m_Second(second),m_cnt(c)
  
};

说明:typename是类型名关键字,个数不限。模板里面也可以有非类型的参数,原则上只能是整数,而且是字面量(编译时就确定下来);也可以有默认值。

最好不要把模板的声明与定义分开,因为若是成员函数中有类型参数存在,则需要在成员函数定义之前进行模板声明,并且在成员函数名前加上“ 类名<类型参数>::“

想查看实际替换时是什么类型,这就需要运行时类型识别函数了typeid

#include<iostream>
#include<string>
#include<typeinfo>
using namespace std;

template<typename T>
class test
{
public:
  static string name();
};

//类外函数定义
template<typename T>     //必须添加表明下面是模板
string test<T>::name()   //类外定义静态成员函数不能加static,与静态变量赋值类似
{
  return typeid(T).name();
}

//类模板特化
template<>   //必须
class test<char>
{
public:
  static string name(){return "const char*";}
};

template<typename T>
class test<T*>
{
public:
  static string name(){ return test<T>::name()+"_pointer";}
};
int main()
{
  cout <<"string:" <<  test<string>::name() <<endl; //静态类的调用方法
  cout << "char:"  << test<char>::name() << endl;
  cout << "char*"   << test<char*>::name() << endl;
 return 0;
}


模板偏特化

模板偏特化是通过"给模板中的部分模板参数以具体的类,而留下剩余的模板参数仍然使用原来的泛化定义"的方式来实现的

#include<iostream>
using namespace std;

template <int n>           //无类型参数
class fact
{
public:
  enum {val = fact<n-1>::val*n};
};

template<>
class fact<0>                //特化
{
public:
  enum{val = 1};
};

int main()
{
  cout << fact<6>::val << endl;  //模板实例化
  return 0;
}


全特化

//模板全特化 对比1 2中模板格式
template<>
class test<int*,char,1024>
{
  private:
  string  m_First;
  T2  m_Second;
  int m_cnt;
public:
  test(int* first,char second,int c=1024):m_First(first),m_Second(second),m_cnt(c)
};

模板,偏特化,全特化,最佳匹配

.当你实例化一个模板时,编译器会把目前存在的偏特化模板和全特化模板做比较,并找出其中最合适、最匹配的实现.

//测试匹配偏特化,全特化
#include<iostream>
using namespace std;

template<typename T1,typename T2>
class test
{
public:
  void name(){cout << "类模板" << endl;}
};

//偏特化1
template<typename T1>
class test<T1,int>
{
public:
  void name(){cout << "偏特化,T2 = int"<< endl;}
};

//偏特化2 与偏特化1产生二义性
// template<typename T1>
// class test<T1,T1>
// {
// public:
//   void name(){cout << "偏特化,同类型匹配" <<endl;}
// };

//全特化
// template<>
// class test<int,int>
// {
// public:
//   void name(){cout << "全特化:int int" << endl;}
// };

int main()
{
  test<int,int>().name();
  return 0;
}

函数模板

template<typename T>
T Max(T a,T b)
{
  return a>b?a:b;
}

匹配:函数模板可以根据实参的传值类型自动生成对应类型函数,但是返回值必须指定,因为返回值是不可推断的

偏特化:函数模板只支持全特化,不支持偏特化

函数模板重载: 函数模板与同名的非模板函数可以重载,这种情况下,调用时先找参数完全匹配的非模板函数,如果找不到就调用匹配的模板函数。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

//普通函数模板
template<typename T>
void sort(T a[], int n)
{
	for(int i=0; i<n-1; i++)
	{
		int min = i;
		for(int j=i+1; j<n; j++)
			if(a[j]<a[min])
				min = j;
		swap(a[min],a[i]);
	}
}

//特化模板1字符串指针
template<>
void sort(const char* a[], int n)
{
	for(int i=0; i<n-1; i++)
	{
		int min = i;
		for(int j=i+1; j<n; j++)
			if(strcmp(a[j],a[min])==-1)//字符串比较-1 0 1
				min = j;
		swap(a[min],a[i]);
	}
}

//特化模板2指针
template<typename T>
void sort(T* a[], int n)
{
	for(int i=0; i<n-1; i++)
	{
		int min = i;
		for(int j=i+1; j<n; j++)
			if(*a[j]<*a[min])
				min = j;
		swap(a[min],a[i]);
	}
}

//重载<操作符,完成结构体排序
class date
{
  int year;
  int month;
  int day;
public:
  date(int y,int m,int d):year(y),month(m),day(d){}
  bool operator<(const date& d)const
  {
	if(this->year < d.year) return 1;
	else if(this->year == d.year)
	{
	  if(this->month < d.month) return 1;
	  else if(this->month == d.month)
	  {
		if(this->day < d.day) return 1;
	  }
	}
	return 0; 
  }
  friend ostream& operator<<(ostream& os,const date& d)
  {
	return os<< d.year <<"-"<<d.month << "-" << d.day;
  }
};

//输出数组元素的内容
template<typename T>
void show(T a[],int n) // n = sizeof(a)/sizeof(a[0]);
{
  for(int i = 0 ;i < n; i++)
  {
	cout << a[i] << " ";
  }
  cout << endl;
}

template<typename T>
void show(T *a[],int n)
{
  for(int i = 0 ;i < n; i++)
  {
	cout << *a[i] << " ";
  }
  cout << endl;
}

int main()
{
  //普通模板测试
  double d[5] = {12.5,45.6,3.2,99.9,56.89};
  sort(d,5);
  show(d,5);
  //字符串指针模板测试
  const char* str[3] = {"hello","world","thanks"};
  sort(str,3);
  show(str,3);
  
  //指针数组测试
  int *ptri[5] = {new int(5),new int(45),new int(58),new int(99),new int(158)};
  sort(ptri,5);
  show(ptri,5);
  
  //date结构体测试
  date dd[3] = {{1998,10,12},{2012,12,12},{2014,3,21}};
  sort(dd,3);
  show(dd,3);
  return 0;
}


输出结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值