59、类模板深度剖析

1、多参数类模板

  • 类模板可以定义任意多个不同的类型参数
template <typename T1, typename T2>
class Test
{
public:
	void add(T1 a, T2 b);
};
Test <int, float> t;				//定义对象
  • 类模板可以被特化
    — 指定类模板的特定实现
    部分类型参数必须显示指定
    — 根据类型参数分开实现类模板

在这里插入图片描述

  • 类模板的特化类型
    部分特化 — 用特定规则约束类型参数
    完全特化 — 完全显示指定类型参数
    在这里插入图片描述

特化是建立在类模板的基础上的,有类模板之后,才分为部分特化和完全特化。只要是特化,就必须在class Test 后面加上 <(含参数)>

部分特化我个人觉得它是一个小模板,class Test 后面加上< 参数 >
完全特化我个人觉得它具体到了某一个类型,class Test 后面加上 < >

类模板一般都要在主函数里面明确写上类型

#include <iostream>
#include <string>

using namespace std;

template <typename T1, typename T2>
class Test
{
public:
	void add(T1 a, T2 b)
	{
		cout << "void add(T1 a, T2 b)" << endl;
		cout << a + b << endl;
	}
};

template <typename T1, typename T2>			//部分特化
class Test < T1*, T2* >
{
public:
	void add(T1* a, T2* b)
	{
		cout << "void add(T1* a, T2* b)" << endl;
		cout << *a + *b << endl;
	}
};

template <typename T>			//部分特化
class Test < T, T >				//当Test 类模板的两个类型参数完全相同时,使用这个实现
{
public:
	void add(T a, T b)
	{
		cout << "void add(T a, T b)" << endl;
		cout << a + b << endl;
	}
	void print()
	{
		cout << "class Test < T, T >" << endl;
	}
};

template <>				        //完全特化
class Test <void*, void*>	    //T1 = void*并且T2 = void*时,使用这个实现
{
public:
	void add(void* a, void* b)
	{
		cout << "void add(void* a, void* b)" << endl;
		cout << "Error to add void* " << endl;
	}
};
int main()
{
	Test <int, float> t1;
	Test <double, double> t2;
	Test <void*, void*> t3;

	t1.add(1, 0.5);
	
	t2.add(3.0, 4.0);
	t2.print();

	t3.add(NULL, NULL);
	
	Test <int*, double*> t4;
	int a = 1;
	double b = 0.1;
	t4.add(&a, &b);

	return 0;
}

在这里插入图片描述

  • 类模板特化注意事项
    — 特化只是模板的分开实现
    — 本质是同一个类模板
    — 必须显示指定每一个类型参数

2、问题

类模板和重定义有区别吗?函数模板可以特化吗?


3、特化的深度解析

  • 重定义和特化的不同
    — 重定义
      1、一个类模板和一个新类(或者两个类模板)
      2、使用时需要考虑如何选择的问题
    — 特化
      1、以统一的方式使用类模板和特化类
      2、编译器自动优先选择特化类
  • 函数模板只支持类型参数完全特化

程序一:(重定义和特化的不同)

#include <iostream>
#include <string>

using namespace std;

template <typename T1, typename T2>
class Test
{
public:
	void Add(T1 a, T2 b)
	{
		cout << "void Add(T1 a, T2 b)" << endl;
		cout << a + b << endl;
	}
};

template <typename T1, typename T2>
class Test <T1*, T2*>
{
public:
	void Add(T1* a, T2* b)
	{
		cout << "void Add(T1* a, T2* b)" << endl;
		cout << *a + *b << endl;
	}
};

template <typename T>
class Test < T, T >
{
public:
	void Add(T a, T b)
	{
		cout << "void Add(T a, T b)" << endl;
		cout << a + b << endl;
	}
};

//template <>
//class Test < void*, void* >
//{
//public:
//	void Add(void* a, void* b)
//	{
//		cout << "void Add(void* a, void* b)" << endl;
//		cout << "Error" << endl;
//	}
//};

class Test_new
{
public:
	void Add(void* a, void* b)
	{
		cout << "void Add(void* a, void* b)" << endl;
		cout << "Error" << endl;
	}
};
int main()
{
	Test <int, double> t1;
	Test <double, double> t2;
	//Test <void*, void*> t3;
	Test <int*, double*> t4;

	t1.Add(1, 1.1);
	t2.Add(2.2, 2.8);
	//t3.Add(NULL, NULL);

	int a = 1;
	double b = 2.1;
	t4.Add(&a, &b);

	Test_new t3;
	t3.Add(NULL, NULL);
	return 0;
}

在这里插入图片描述
分析:程序的第50行重新定义了类,也可以实现之前我们特化的功能,但是在能用特化的情况下,还是不要重定义。


程序二:(函数模板)

template <typename T>		//函数模板定义
bool equal(T a, T b)
{
	return a == b;
}

template <>					//函数模板完全特化
bool equal <void*> (void* a, void* b)
{
	return a == b;
}
#include <iostream>
#include <string>

using namespace std;

template <typename T>			//定义函数模板
bool Equal(T a, T b)
{
	cout << "bool Equal(T a, T b)" << endl;
	return a == b;
}

template <>						//函数模板完全特化
bool Equal <double> (double a, double b)
{
	cout << "bool Equal <double> (double a, double b)" << endl;
	const double delta = 0.00000001;
	double r = a - b;
	return (-delta < r) && (r < delta);
}
int main()
{
	cout << Equal(1, 1) << endl;
	cout << Equal(0.001, 0.001) << endl;

	return 0;
}

在这里插入图片描述

#include <iostream>
#include <string>

using namespace std;

template <typename T>
bool Equal(T a, T b)
{
	cout << "bool Equal(T a, T b)" << endl;
	return a == b;
}

bool Equal(double a, double b)
{
	cout << "bool Equal (double a, double b)" << endl;
	const double delta = 0.00000001;
	double r = a - b;
	return (-delta < r) && (r < delta);
}
int main()
{
	cout << Equal(1, 1) << endl;
	cout << Equal(0.001, 0.001) << endl;
	cout << Equal<>(0.001, 0.001) << endl;

	return 0;
}

在这里插入图片描述
分析:这个程序就是我们在刚开始学习函数模板时候的程序。函数模板和函数重载同时存在会先调用函数重载,如果一定要调用函数模板,在函数名和参数之间加上<>就会默认调用模板(空模板实参列表),详见57课的第3节重载函数模板。

  • 工程中的建议
    当需要函数模板时,优先考虑使用模板特化;当模板特化无法满足要求,再使用函数重载

小结:

  • 类模板可以定义任意多个不同的类型参数
  • 类模板可以被部分特化完全特化
  • 特化的本质是模板的分开实现
  • 函数模板只支持完全特化
  • 工程中使用模板特化代替类(函数)重定义
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值