函数模板--C++

引出

当在C++中要实现一个通用的交换函数, 因如何实现

void Swap(int& left, int& right) 
{    
	int temp = left;    
	left = right;   
	right = temp; 
}
 
void Swap(double& left, double& right) 
{
    double temp = left;
    left = right;
    right = temp; 
}
 
void Swap(char& left, char& right) 
{    
	char temp = left;
    left = right;
    right = temp;
}
......

使用函数重载虽然可以实现,但是有一下几个不好的地方:

  1. 重载的函数仅仅只是类型不同,代码的复用率比较低,只要有新类型出现时,就需要增加对应的函数
  2. 代码的可维护性比较低,一个出错可能所有的重载均出错

使用模板, 相当于告诉编译器一个模子, 就能节省很多代码
模板分为函数模板类模板

函数模板

示例:

template<typename T> 
void Swap( T& left,  T& right) 
{    
	T temp = left;    
	left = right;    
	right = temp; 
}

这样就能实现多种基本类型的交换, 调用方法与一般的函数相同, 编译器会自己产生相关代码
注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)

类模板

格式:

template<class T1, class T2, ..., class Tn>
 class 类模板名 
 {    
 	// 类内成员定义 
 };

类模板的使用参见: 类模板的使用
注意:模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<> 中即可,类模板名字不是真正的类,而实例化的结果才是真正的类

模板的参数

上面能看到模板的参数如下
template< class T>
实际上模板的参数多种多样, 模板参数分为:

  1. 类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。
  2. 非类型形参,就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。
template<class T, size_t N = 10>   
class array   
{ 
private:
        T _array[N];        
        size_t _size;    
...
} 

当定义数组时, 数组的长度一般必须传一个常量值, 不能传变量
使用非类型形参就能够传数组的长度
注意

  1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的。
  2. 非类型的模板参数必须在编译期就能确认结果。

模板的特化

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结 果,比如:

函数模板特化

template<class T> 
bool IsEqual(T& left, T& right) 
{    return left == right; }
 
void Test() 
{    char* p1 = "hello";    
	char* p2 = "world";
 
    if(IsEqual(p1, p2))
        cout<<p1<<endl; 
    else       
        cout<<p2<<endl; 
}

此时,就需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。模板特 化中分为函数模板特化与类模板特化
函数模板的特化步骤:

  1. 必须要先有一个基础的函数模板
  2. 关键字template后面接一对空的尖括号<>
  3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误
template<> 
bool IsEqual<char*>(char*& left, char*& right) 
{    if(strcmp(left, right) > 0)        
		return true;        
	return false; 
}

类模板特化

template<class T1, class T2> 
class Data 
{ 
public:    
	Data() {cout<<"Data<T1, T2>" <<endl;} 
private:    
	T1 _d1;   
	T2 _d2; 
};
 
template<> 
class Data<int, char> 
{
 public:    
 	Data() {cout<<"Data<int, char>" <<endl;} 
 private:    
 	T1 _d1;    
 	T2 _d2; 
 };
 
void TestVector() 
{    
	Data<int, int> d1;   
	Data<int, char> d2; 
}

当然也可以只特化一个参数, 叫偏特化

总结

优点:

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性

缺点:

  1. 模板会导致代码膨胀问题,也会导致编译时间变长
  2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误
发布了53 篇原创文章 · 获赞 46 · 访问量 7228

猜你喜欢

转载自blog.csdn.net/new_bee_01/article/details/102715122