模板初阶(函数模板和类模板)

文章目录

  • 1.函数模板
    • 1.1函数模板定义格式
    • 1.2关于模板实例化的一些小问题
  • 2.类模板
    • 2.1 类模板的定义格式

1.函数模板

1.1函数模板定义格式

模板源于C语言一些短板没有解决

#include 
#include
using namespace std;
void Swap(int& left,int& right)
{
	int temp = left;
	left = right;
	right = temp;
}
void Swap(double& left, double& right)
{
	double temp = left;
	left = right;
	right = temp;
}
int main()
{
	int a = 1, b = 2;
	Swap(a, b);
	double c = 1.11, d = 2.2;
		Swap(c, d);
	return 0;
}

有一个就交换一个,太麻烦。
C++用泛型编程改进——模板。
模板初阶(函数模板和类模板)_第1张图片
无论多少类型模板需要交换,只需要一个模板就可以

template<class T> ,函数列表的参数模板。
template<typename T>
//函数模板
template<class T>//具体类型是什么不知道
void Swap(T& x, T& y)
{
	T tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 1, b = 2;
	//Swap(a, b);
	swap(a,b);//C++库里面有一个,不需要自己写
	double c = 1.11, d = 2.2;
		//Swap(c, d);
		swap(c,d);
	return 0;
}

ab和cd调用的不是同一个函数。栈帧也不一样大。
函数模板原理(蓝图,不是函数):并没有减少函数,本质是T实例化是int/double的代码。调用的是模板最后实例化生成的代码。模板的原理是把工作交给了编译器去做。
定义多个模板参数:

template<class X,class Y>
Void Func()
{
}

模板初阶(函数模板和类模板)_第2张图片

1.2关于模板实例化的一些小问题

  1. 隐式实例化:让编译器根据实参推演模板参数的实际类型
template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.0, d2 = 20.0;
//隐式实例化
	//实参传递给形参,自动推演类型。
	Add(a1, a2);
	Add(d1, d2);//可以编译通过
	
	Add(a1, d1);//编译不能通过,对模板参数T 不明确
	
//自己强制转化
    Add(a1, (int)d1);//强转,此时没有歧义
    Add((double)a1, d1);

//显式实例化:在函数名后的<>中指定模板参数的实际类型,自己实例化指定。
    //在函数名和函数列表中间加一个模板参数
    Add<int>(a1, d1)//传参时隐式类型转换
    
	return 0;

}
  1. 显式实例化:在函数名后的<>中指定模板参数的实际类型
    如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。
//专门处理int的加法函数
int Add(int left, int right)
{
	return left + right;
}
//通用加法函数
template<class T>
T Add( T left,  T right)
{
	return left + right;
}
 //编译器遇到问题的时候会传特别匹配的那一个
template<class T1,class T2>
{
T Add(T1 left, T2 right)
  { 
   return left + right;
  }
}

   
//可以同时存在

int main()
{
   int a=1,b=2;
   Add(a,b);//调用第一个,因为调用第一个的成本更低,调用第二个需要先实例化
   //如果要求必须用第二个
   Add<int>(a,b);
   
   return 0}

2.类模板

2.1 类模板的定义格式


template<class T1,class T2,...class Tn>
class 类模板名
{
	//类内成员定义
};
//typedef double STDataType;随意改变类型
typedef int STDataType;//可以解决部分问题
class Stack
{
private:
	STDataType * _a;
    size_t _top;
    size_t _capacity;

}
int main()
{
//两份类的代码几乎是一致的
	Stack st1;
	Stack st2;
//但不能做到一个暂存int,第二个暂存double
	return 0;
}

改进:


template<class T>
class Stack
{
	public:
	Stack(int capacity=4)
	{
	  _a=new T[capacity];
	  _top=0;
	  _capacity=capacity;
	}
	~Stack()
	{
	 delete[] _a;
	 _capacity=_top=0;//一定要匹配使用
	}
	 
private:
	T* _a;
	size_t _top;
	size_t _capacity;
};
int main()
{
 Stack<int> st1;//int
 Stack<double> st2;//double
 
 vector<int> v;//顺序表,实例化一份数据是int的
 //遍历vector
 for(size_t i=0;i<v.size();++i)
 {
 //运算符重载
   cout<<v[i]<<" ";
   return 0;
}

类模板只能显式实例化

你可能感兴趣的:(c++,笔记,经验分享)