C++之初识模板

C++之初识模板

文章目录

  • C++之初识模板
    • 1. 函数模板
      • 1.1 概念
      • 1.2 格式
      • 1.3 函数模板的实例化
      • 1.4 函数模板的匹配规则
    • 2. 类模板
      • 2.1 格式
      • 2.2 类模板实例化

1. 函数模板

void Swap(int& left, int& right)
{
	int tmp = left;
	left = right;
	right = tmp;
}

  上述代码是一个简单的交换函数,但是只能用来交换int,要想交换其他类型的变量,则需要重新写一个,但是代码的重复率极高,只有参数类型不一样,为了提高代码的复用率,C++提出了模板

1.1 概念

  函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定
类型版本

1.2 格式

template<typename T1,typename T2,...,typename Tn>
void Swap(T& left,  T& right)
{
	T tmp = left;
	left = right;
	right = tmp;
}

template
函数返回值 函数名(参数列表) {}

  与定义普通函数相似,只不过在函数名上加上了template,然后在函数中将与类型无关的通用代码用T来替换,

  • template是模板的意思
  • typename 是用来定义模板的参数,也可以使用class
  • T只是一个变量名,编译器会通过参数来推导T的类型

注意:
  函数模板只是一张蓝图,并不是一个函数,是编译器用使用方式产生特定具体类型函数的模具,是编译器帮我们多做了事情

  • 在编译阶段,编译器会通过传入的实参类型进行推导,并生成对应类型的函数

1.3 函数模板的实例化

  函数模板的实例化分为隐式实例化和显式实例化

  • 隐式实例化
#include 
using namespace std;

template<class T>
T Add(T left, T right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double c1 = 30.4,c2 = 50.6;
	Add(a1, a2);
	Add(c1, c2);
	
	//Add(a1, c1); //报错
	return 0;
}

  编译器在推导T的类型时,a1为int的类型,而c1为double的类型,但是模板中只有一个T,无法推导出T的类型是什么类型,所以会报错
  注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅

解决方法:

    1. 自己强制转换: Add(a1, (int)c1);
    1. 显式实例化: Add(a1, c1);

  • 显式实例化:
#include 
using namespace std;

template<class T>
T Add(T left, T right)
{
	return left + right;
}
int main()
{
	int a = 10;
	double b = 20.4;
	Add<int>(a, b);
	return 0;
}

  在函数调用时指定模板参数的类型,编译器会进行隐式的类型转换,如果无法类型转换则会报错

1.4 函数模板的匹配规则

#include 
using namespace std;

int Add(int left,int right)
{
	cout << "int Add(int left,int right)" << endl;
	return left + right;
}
template<class T>
T Add(T left, T right)
{
	cout << "T Add(T left, T right)" << endl;
	return left + right;
}
template<class T1,class T2>
auto Add(T1 left, T2 right) //auto作为返回值,可以推导返回值类型
{
	cout << "auto Add(T1 left, T2 right)" << endl;
	return left + right;
}
int main()
{
	Add(1, 2);      //调用int Add(int left,int right)
	Add<int>(1, 2); //显式实例化调用调用T Add(T left, T right)
	Add(1.1, 2);    //调用auto Add(T1 left, T2 right)
	Add(1.1, 2.2);  //调用T Add(T left, T right)
	Add<int,double>(1.1, 2.2);//显式实例化调用调用auto Add(T1 left, T2 right)
	return 0;
}

1. 普通函数可以和模板函数同时存在,函数模板还可以被实例化为这个普通函数>
2. 在调用函数时,会选择最为匹配的函数进行调用

  • 普通函数和模板函数都存在时,优先匹配普通函数(如果参数类型匹配)
  • 没有普通函数,优先匹配函数模版+参数类型匹配
  • 只有任意一种,如果类型转换一下也能用,也可以匹配调用

3. 普通函数默认可以进行隐式类型转换,而函数模板不可以

2. 类模板

2.1 格式

template<class T1,class T2,...,class Tn>
class A
{
public:
	///...
private:
	T* _arr;
	int _top;
	int _capacity;
};

2.2 类模板实例化

注意:类模板只能显式实例化

#include 
#include 
using namespace std;
int main()
{
	stack<int> s1;
	return 0;
}
  • stack是类的名字,stack是s1的类型

你可能感兴趣的:(C++,c++,开发语言,函数模板,类模板,函数模板匹配规则,class,typename)