泛型编程与模板

来源:互联网 发布:当网络写手挣钱吗 编辑:程序博客网 时间:2024/05/17 19:21

        【泛型编程泛型编程让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。泛型即是指具有在多种数据类型上皆可操作的含义。(模板是泛型编程的基础)


 模板:1.函数模板

   2.类模板


【模板函数】:代表了一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型产生函数的 特定类型版本。(模板函数不是真正的函数)


实现一个通用的加法函数:

1.通过函数重载实现:

int Add(int left, int right){return left + right;}char Add(char left, char right){return left + right;}float Add(float left, float right){return left + right;}double Add(double left, double right){return left + right;}


【Add函数实现重载】

优点:函数进行参数类型检测,自行调用与自身类型匹配的函数,调用方便且效率高。

缺点:1.只要有新类型出现,就要重新添加对应函数。

   2.除类型外,所有函数的函数体都相同,代码的复用率不高。

   3.如果函数只是返回值类型不同,函数重载不能解决。

   4.一个方法有问题,所有的方法都有问题,不好维护


2.用函数模板实现

【模板函数的格式】

 template <class Param1,class Param2,...,class Paramn> 

返回值类型  函数名(参数列表)

 {    ... }


template <class T>T Add(T left, T right){return left + right;}int main(){cout << Add(1, 2) << endl;      //3cout << Add(1.1, 2.2) << endl;   //3.3cout << Add('1', '2') << endl;  //c   ('1'的ASCII为49,'2'的ASCII为50,两个之和为99是'c')system("pause");return 0;}

          class是用来定义模板参数关键字,typename也行。(不能使用struct代替class)


<a>模板函数也可以定义为inline(内联)函数

 内联函数是什么:

    C++关键字,在函数声明或定义中函数返回类型前加上关键字inline,即可以把函数指定为内联函数。关键字inline必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前面不起任何作用。inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。一般的,用户可以阅读函数的声明,但是看不到函数的定义。

template <class T>inline T Add(T left, T right){return left + right;}

         注意:inline关键字必须放在模板形参表之后,返回值之前,不能放在template之前


<b>模板函数特性

1.模板函数在运行时根据参数的类型来生成函。

2.模板函数内部,对代码不进行检测。

3.当有实参函数时,当先调用实参函数模板不会合成函数。

4.当有实参函数时,在调用模板时进行了显示实例化,则模板函数会合成函数进行调用。








【实参推演】

<从函数实参确定模板形参类型和值的过程称为模板实参推断

<多个类型形参的实参必须完全匹配


【类型形参转换】

一般不会转换实参以匹配已有的实例化,相反会产生新的实例。

 编译器只会执行两种转换:

 1、const转换:接收const引用或者const指针的函数可以分别用非const对象的引用或者指针来调用

 2、数组或函数到指针的转换:如果模板形参不是引用类型,则对数组或函数类型的实参应用常规指 针转换。数组实参将当做指向其第一个元素的指针,函数实参当做指向函数类型的指针。


【模板函数的参数列表】

1.在函数模板的内部不能指定缺省的模板实参。

2.所有模板形参前面必须加上 class或者typename 


3.模板形参可以是类型形参也可以是非类型形参


5、模板类型形参可作为类型说明符用在模板中的任何地方,与内置类型或自定义类型   使用方法完全相同,可用于指定函数形参类型、返回值、局部变量和强制类型转换 

6、模板形参表中,class和typename具有相同的含义,可以互换,使用typename更加直观。  但关键字typename是作为C++标准加入到C++中的,旧的编译器可能不支持。


【模板函数重载】

模板函数重载与一般函数重载所需条件一样

1.作用域相同

2.函数名相同

3.参数列表不同

template <class T,class N>T Add(T left, N right){return left + right;}template<class T,class N>T Add(T left,T& right){return left + right;}template<class T,class N>T Add(N right, T left){return left + right;}


注:函数重载与返回类型无关

【模板函数特化】

 有时候并不总是能够写出对所有可能被实例化的类型都合适的模板,在某些情况下,通用模板定 义对于某个类型可能是完全错误的,或者不能编译,或者做一些错误的事情。



 当遇到这种比较字符串大小时,上面定义的模板函数无法合成正确的函数,在此我们可以把这种特殊情况重写一个函数,用来处理特殊的类型,


模板函数特化形式如下:

1.关键字template后面接< >

2.函数名后接模板名和< >,尖括号中指定这个特化定义的模板形参

3.函数形参表中形参的类型要与模板形参类型一致


函数格式



注意:在模板特化版本的调用中,实参类型必须与特化版本函数的形参类型完全匹配,如果不匹配,编译器将为实参模板定义中实例化一个实例。




注意:

特化不能出现在模板实例的调用之后,应该在头文件中包含模板特化的声明,然后使用该特化版本的每个源文件包含该头文件。






原创粉丝点击