类模板深度剖析
-
多参数类模板,类模板可以定义多个不同类型的参数
template
<typename T1,typename T2>
class Test
{
public:
void add(T1 a,T2 b);
}
//使用方式
//需要指定每一个类型参数
//int --->T1
//float--->T2
Test<int,float> t;
-
令人惊讶的特性:类模板可以被特化
-
指定类模板的特定实现
-
部分类型参数必须显示指定
-
根据类型参数分开实现类模板
-
如下图所示,我们指定实际类型参数时,如果T1,T2是相同的类型,编译器会优先选择右边的类模板的实现,这两个类模板不会发生同名冲突的问题,编译器会把它们理解为同一个模板,只是根据类型参数来选择是使用哪一个模板。
-
类模板的特化类型
-
部分特化---用特定规则约束类型参数(即使特殊了,参数仍然是一个泛指类型)
-
完全特化---完全显示指定类型参数
-
如下图所示为完全特化:如果要使用Test类模板的时候完全显示指定泛指类型T1,T2都为int的时候,编译器会选择使用右边的完全特化的类模板来实现。
-
类模块特化注意事项
-
特化只是模块的分开实现,本质上是同一个类模块。
-
特化模块的使用方式是统一的,必须是显示指定每一个类型参数
-
范例程序
#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=" << a + b << endl;
}
};
template <typename T>
//当Test类型参数完全相同时,使用这个类模板来实现
//编译器不会把它当成一个新的模板,只会把它看成Test模板的一种特殊的实现。
//部分特化
class Test<T, T>
{
public:
void Add(T a, T b)
{
cout << "void Add(T a, T b)" << endl;
cout << "a+b=" << a + b << endl;
}
};
//当Test类型参数都为void*类型是,使用这个类模板来实现
//完全特化
template < >
class Test<void*, void*>
{
public:
void Add(void* a,void* b)
{
cout << "void add(void* a,void* b)" << endl;
cout << "Error to add void* Param " << 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=" << *a + *b << endl;
}
};
int main()
{
Test<int, float> t1;
Test<long, long> t2;
Test<void*, void*> t3;
Test<int*, double*> t4;
int a = 2;
double b = 3.14;
t1.Add(1,2.5);
t2.Add(2,3);
t3.Add(NULL,NULL);
t4.Add(&a,&b);
}
-
运行结果
void Add(T1 a,T2 b)
a+b=3.5
void Add(T a, T b)
a+b=5
void add(void* a,void* b)
Error to add void* Param
void Add(T1* a,T2* b)
*a+*b=5.14
-
问题
-
类模板特化与重定义有区别吗?
-
函数模板可以特化吗?
-
重定义和特化的不同
-
重定义:一个类模板和一个新类(或者两个类模板),使用的时候需要考虑如何选择的问题。
-
特化:以统一的方式使用类模板和特化类,编译器自动优先选择特化类
-
函数模板只支持类型参数完全特化
template <template T>
//函数模板定义
bool Equal(T a,T b)
{
return a==b;
}
//函数模板完全特化
template < >
bool Equal<void*>(void* a,void* b)
{
return a==b;
}
-
范例程序
// 函数模板特化实验.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
using namespace std;
template <typename T1,typename T2>
bool Equal(T1 a,T2 b)
{
cout << "bool Equal(T1 a,T2 b)" << endl;
return a == b;
}
//函数模板完全特化
template <>
bool Equal<double>(double a,double b)
{
const double detla = 0.0000000000001;
double r = a - b;
cout << "bool Equal<double>(double a,double b)" << endl;
return (-detla < r) && (r < detla);
}
bool Equal(double a,double b)
{
const double detla = 0.0000000000001;
double r = a - b;
cout << "bool Equal(double a,double b)" << endl;
return (-detla < r) && (r < detla);
}
int main()
{
//调用的是函数模板
cout << Equal(1, 2) << endl;
//默认调用全局函数
cout << Equal(0.1,0.1) << endl;
//调用特化后的函数模板
cout << Equal<double>(0.2, 0.2) << endl;
//带个<>号,告诉编译器放弃全局函数,使用函数模板
cout << Equal<>(0.4, 0.5) << endl;
}
-
运行结果
bool Equal(T1 a,T2 b)
0
bool Equal(double a,double b)
1
bool Equal<double>(double a,double b)
1
bool Equal<double>(double a,double b)
0
-
工程中的建议
当需要重载函数模块时,优先考虑使用模板特化。
当模板特化无法满足需求时,再使用函数重载。
-
小结
-
类模板可以定义任意多个不同的类型参数
-
类模板可以被部分特化和完全特化
-
特化的本质是模板的分开实现
-
函数模板只支持完全特化
-
工程中使用模板特化代替类(函数)重定义
主要记录的是学习听课的笔记