c++模板

模板定义

模板是实现代码重用机制的一种工具,可以实现类型参数化(把类型定义为参数)
从而实现真正的代码重用性,有两种模板,一种是函数模板,一种是类模板

函数模板

在c++中也存在泛型变成的理念(不考虑具体数据类型的变成方式)
之前我写过一篇unity中c#的使用泛型的方法 大家有兴趣可以去自己查看

就用交换两个值的为例子 假如说我们要交换两个值
我们可能只会每种类型都写一种

void Swap(int a, int b)//int类型
{
	int tmp = a;
	a = b;
	b = tmp;
}
void Swap(double a, double b)//double类型
{
	double tmp = a;
	a = b;
	b = tmp;
}

这样是很有局限性的 我们可以使用函数模板实现代码复用的效果

template <typename T>
void Swap(T& a, T& b)
{
    T tmp = a;
    a = b;
    b = tmp;
}

然后我们测试一下

template <typename T>
void Swap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}
void main()
{
	string a = "12345";
	string b = "54321";
	Swap(a, b);
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
}

在这里插入图片描述
我们需要注意 函数模板是不允许隐式类型转换的

template <typename T1, typename T2, typename T3>
T1 add(T2 a, T3 b)
{
	T1 ret;
	ret = static_cast<T1>(a + b);
	return ret;
}

void main()
{
	int c = 12;
	float d = 23.4;
	cout << add<float>(c, d) << endl;	//返回值在第一个类型参数中指定
	cout << add<int, int, float>(c, d) << endl;
	system("pause");
}

在这里插入图片描述
可以看到两种输出类型是不一样的

再就是我们测试一下几种函数的调用先后顺序


template <typename T>
void fun(T a)
{
	cout << "void fun(T1 a)" << endl;
}

template <typename T1, typename T2>
void fun(T1 a, T2 b)
{
	cout << "void fun(T1 a, T2 b)" << endl;
}

void fun(int a, float b)
{
	cout << "void fun(int a, float b)" << endl;
}

void main()
{
	int a = 0;
	float b = 0.0;
	fun(a);
	fun(a, b);	//普通函数void fun(int a, float b)已经能完美匹配,于是调用普通函数
	fun(b, a);	//这个调用,函数模板有更好的匹配,于是调用函数模板
	fun<>(a, b);	//限定只使用函数模板
}

然后看运行结果
在这里插入图片描述

函数模板特化

注意函数模板特化只有全特化,没有偏特化


//普通模板
template<class T1, class T2>
bool Compare(T1 a, T2 b)
{
	cout << "普通模板" << endl;
	return a == b;
}

//函数模板特化
template<>
bool Compare(const char* a, const char* b)
{
	cout << "函数模板特化" << endl;
	return strcmp(a, b) == 0;
}

类模板

template <类型形式参数>
    class 类名
    {
     //类声明体;
    };
    
    template <类型形式参数>
    返回类型 类名 <类型> :: 成员函数名1(形式参数)
    {
     //成员函数定义体;
    }

    ... ...
    template <类型形式参数>
    返回类型 类名 <类型> :: 函数名N(形式参数)
    {
  //成员函数定义体;
    }

//例子
template<class T1, class T2>
class Test
{
public:
	Test(T1 a, T2 b) :_a(a), _b(b)
	{
		cout << "模板化" << endl;
	}
private:
	T1 _a;
	T2 _b;
};

类模板全特化

这个知识有点重要,我在面试题中见过面试官问这个
所谓模板全特化就是限定死模板实现的具体类型

//模板全特化
template<>
class Test<int,int>
{
public:
 Test(int a, int b) :_a(a), _b(b)
 {
  cout << "模板全特化" << endl;
 }
private:
 int _a;
 int _b;
};

模板偏特化

偏特化我们可以和特化来比较记忆
模板全特化是限定死所有的实现类型,而模板片特化是只限定一部分实现类型

//模板偏特化
template<class T>
class Test<int,T>
{
public:
 Test(int a, T b) :_a(a), _b(b)
 {
  cout << "模板偏特化" << endl;
 }
private:
 int _a;
 T _b;
};

总结

1.函数模板只有全特化,没有偏特化

2.模板,模板的特化,模板的偏特化都存在的情况下,编译器在编译阶段进行匹配,优先特殊的

3.函数模板不能是虚函数,因为每个包含虚函数的类具有一个虚函数表,包含所有虚函数的地址,因此虚函数大小确定
模板只有被使用的时候才能实例化,将其声明为虚函数会使虚函数表的大小不确定,所以成员函数模板不能为虚函数

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值