温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

c++类模板深度剖析

发布时间:2020-07-30 15:10:11 来源:网络 阅读:234 作者:小溢 栏目:编程语言
1、类模板的泛指类型可以定义多个 template <typename T1, typename T2> class Test { public:	void add(T1 a, T2, b); }; 使用时: Test<int, float> t1;	//T1的泛指类型就是int, T2的泛指类型就是float。 2、类模板的特化类型 (1)意思就是如果定义了一个类模板,这个类模板的参数有多个,但是如果当使用这个类模板的时候,我们传递参数时,参数的类型是一样的话,编译器就会将类模板特化成一个参数的类模板。 (2)类模板的特化分为:部分特化,和完全特化。 部分特化:用特定规则约束类型参数,部分类型参数必须显示指定,根据类型参数分开实现类模板 如: template	特化后	template < typename T1, typname T2 >	< typename T > class Test	class Test <T, T>	//部分特化的约束条件 {	{ };	}; 当类型参数不同的时候,会选择用左边的那个类模板,当类型参数相同的时候。class Test< T, T>就是约束条件 完全特化:完全显示指定类型参数 如: template	特化后	template < typename T1, typname T2 >	<  >	//完全特化时,不需要声明泛指类型 class Test	class Test <int, int> //这个就是完全特化 {	{ };	}; 当使用类模板的时候,并且指定了所有的类型参数全都是一样的,比如int的时候,编译器就会将左边的类模板特化成右边的类模板,此时该类模板中就没有泛指类型了。 当类型参数不同的时候,就会使用左边的类模板。 (3)根据实验的例子,类模板的特化就是程序中有了一个左边的类模板的时候(这个类模板的有两个泛指类型),但是同时程序中我们又定义了一个同名的类模板,但是这个类模板的两个泛指类型都是一样的。这个时候,当我们在程序中使用这个类模板的时候,如果参数类型是不一样的,编译器就会使用左边的那个,如果参数类型是一样的时候,编译器就会使用右面的那个。编译器会认为右边的那个类模板,是左边的类模板的一种特化,编译器不会认为左边的类模板是一个新的类模板,只是一个左边类模板的一个特化,所以编译能够通过。 总结:将一个类模板,根据不同的类型参数情况进行分开实现这个类模板,其实就是一个类模板的特化过程。 例: #include <iostream> 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 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(void)	//即使多出来了个print成员函数,编译也是通过的,所以是支持这种特化方式的	{	cout << "class Test < T, T >	" << endl;	} }; /******************************************************完全特化**********************************************************/ template < >	//进行类模板的完全特化时,不用进行泛指类型的声明 class Test <void *, void *>	//当使用Test类模板时,参数类型都为void *时,就会使用这个实现。 { public:	void add(void * a, void * b)	{	cout << "void add(void * a, void * b)" << endl;	cout << "Error run not to add because type is void *..." << endl;	} }; /*****************************************将Test类模板特化出一个两个参数分别是指针的情况**********************************************/ 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;	} }; int main(void) {	int a = 1;	double b = 1.0;	Test<int, float> t1;	//使用的就是没有特化的Test类模板	Test<long, long> t2;	//使用的就是特化后的Test类模板	Test<void *, void *> t3;	Test<int *, double *> t4;	t1.add(2, 2.5);	t2.add(10, 10);	t2.print();	t3.add(&a, &b);	t4.add(&a, &b);	return 0; } 3、继续理解类模板的特化 (1)类模板的特化的就是根据需要,将一个类模板进行分开来实现。特化只是模板的分开实现,本质上还是同一个类模板。特化类模板的使用方式是统一的,就是必须显示的指定每一个类型参数。 (2)问题:类模板特化与重定义有区别吗? 答:有区别,重定义和特化不同。在本质上,如果将一个类模板进行重定义,那么要么就是实现了一个新的类,要么就是最后会出现两个类模板。本质上不同。使用的时候不能进行统一使用, 在使用时我们要考虑选择哪个。 特化的本质是,只实现同一个类模板,只不过这个类模板是分开来实现的,这就是本质上的不同。在使用时是用统一的方式进行使用类模板和特化类,因为本质上都是实现了一个类模板,使用时 编译器会根据不同的参数类型来选择去使用那个类模板还是特化类。所以类模板的特化就是将一个类模板进行分开来实现,这句话是非常重要的。 (3)问题:函数模板可以特化吗? 答:函数模板只支持类型参数的完全特化,不支持部分特化,也就是在函数名的后面显示的指定出具体的参数类型。 如:函数模板的完全特化 template < typename T > bool Equal(T a, T b)	//函数模板的定义 {	return a == b; } template < > bool Equal<void *>(void *, void *)	//函数模板的完全特化 {	return a == b; } (4)工程中的建议:当需要重载函数模板的时候,我们要优先考虑使用模板特化的方式去分开实现一个函数模板,而是不用重载函数模板的方式去新的实现了一个函数,当模板特化无法满足要 求的时候,在使用函数重载。 工程中使用模板特化来代替类(函数)重定义。 例:类模板的部分特化、完全特化,函数模板的完全特化。优先考虑使用特化的方式当需要将模板进行重定义添加功能时。 #include <iostream> #include <string> using namespace std; /* *	特化的方式实现一个类模板,本质就是分开实现类模板 * */ template <typename T1, typename T2>  class Why { public:	void print(T1 a, T2 b)	{	cout << "void print(T1 a, T2 b)" << endl;	cout << a << " " << b << endl;	} }; template <typename T> class Why<T, T>	//为类模板的部分特化 { public:	void print(T a, T b)	{	cout << "void print(T a, T b)" << endl;	cout << a << " " << b << endl;	} }; template < > class Why<int, int>	//为类模板的完全特化 { public:	void print(int a, int b)	{	cout << "void print(int a, int b)" << endl;	cout << a << " " << b << endl;	} }; /* *	函数模板的特化只支持完全特化 *	实现一个函数模板,并且完全特化,也就是分开实现一个函数模板,这样叫做特化。 */ template  <typename T> bool Equal(T a, T b) {	return a == b; } template < >	//函数模板的完全特化,之所以要特化这个函数模板是因为,浮点数的比较不单纯的只用==来比较。 bool Equal<double>(double a, double b) {	const double delta = 0.00000000001;	double r = a - b;	cout << "bool Equal<double>(double a, double b)" << endl;	return ((-delta < r) && (r < delta));  } /* *	重载Equal函数的方式来达到比较浮点数的方法,但这种方式是不优先考虑的,因为这种方式,在使用的时候要考虑如何选择,要优先考虑使用特化的方式。 *	能使用特化的方式时,就不考虑使用这种函数重载的方式,不论对于类模板还是函数模板都是这样的,优先考虑使用特化的方式来分开实现,因为这样都是为了实现一个类模板或函数模板。 */ bool Equal(double a, double b) {	const double delta = 0.00000000001;	double r = a - b;	cout << "bool Equal(double a, double b)" << endl;	return ((-delta < r) && (r < delta)); } int main(void) {	double a = 0.0, b = 0.0;	Why<int, double> w1;	Why<string, string> w2;	Why<int, int>w3;	w2.print("why", "fangqingqing");	w1.print(1, 2.2);	w3.print(100,100);	cout << "Please input two double number..." << endl;	cin >> a >> b;	cout << Equal<double>(a, b) << endl;	cin >> a >> b;	cout << Equal(a, b) << endl;	return 0; }


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI