模板1

模板,即是一种泛型编程,包扩类模板和函数模板。实际上就是为了类或函数的通用性,将类型参数化。

1.函数模板实现方式:

template<typename T>
void fun(T data){}

    关键字template总放在模板定义的最前面。关键字后面是模板参数列表,与函数参数列表类似,不同之处在于用尖括号(<>)括起来,且不能为空。 模板参数可以是模板类型参数(一种类型),也可以是模板非类型参数(一个常量表达式)。如:

template<typename T,char ch,int size...>   //非模板类型参数可以为指针,但不可用double和flout

     模板参数类型的参数由关键字class或typename后加个标识符构成, 两个关键字意义相同,可任意使用。但这里的class和类定义中的class要分清。 标识符为任意字母组合,但一般用T或C,它代表一个内置的或用户自定义的类型( 当它是指针类型时要注意const的修饰)

小知识点:

(1)如果在全局域中声明了模板参数同名的对象、函数或类型,则该全局名将被隐藏。

(2)在函数模板定义中声明的对象或类型不能与模板参数同名。

(3)模板参数名在同一模板参数表中只能被使用一次,但模板参数名可以在多个函数模板或定义之间被重复使用。

(4)一个模板的定义和多个声明所使用的模板参数名无需相同。

(5)函数模板也可以被声明为inline或extern,指示符放在参数表后面,函数定义前面。

2.函数模板的实例化:

函数模板在未实例化前相当于一个类型,是不进行编译的。只有在模板实例化时才会进行编译。

(1)隐式实例化:通过函数调用的方式实例化函数模板的过程被称为模板实参推演

template<typename T,char ch,int size...>   //非模板类型参数可以为指针,但不可用double和flout

(2)显示实例化:提前指定模板,实例化一份

//显示实例化:
template void fun<int>(int  a);

(3)提前声明:

template<typename T>
void fun(T a);

 模板函数:函数模板实例化后的函数。
(4)函数模板推演:

     ①根据参数类型

     ②不可有二异性

3.模板的特例化:计算机实例化过程中会出现逻辑错误的。如:

template<>
void fun<char *>(char * a){}

4.调用顺序:

    优先调用非模板函数 ->特例化的->通过模板实例化的 -> 特例化优化类型 -> 报错
5.函数模板的重载

// 类模板 Array 的定义

template <typename Type>
class Array{ /* ... */ };

// min() 的三个函数模扳声明
template <typename Type>
Type min( const Array<Type>&, int ); // #1
template <typename Type>
Type min( const Type*, int ); // #2
template <typename Type>
Type min( Type, Type ); // #3

   注意:成功的声明一组重载函数模板并不能保证它们可以被成功的调用。在调用一个模板实例时,重载的函数模板可能会导致二义性。如:

template <typename T>
int min( T, T ) { /* ... */ }
template<typename T,typename U>
int min(T,U){ /*...*/ } 

   这两个模板函数是重载的,但当调用时为(int,int)的相同类型参数的调用时,两个函数模板都可以实例化,这时就产生了二义性。因为min(T,U)处理的调用集是min(T,T)处理的超集,所以应该保留min(T,U)的函数模板,删除min(T,T)的函数模板。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/Dxiaoru/article/details/78258875