---恢复内容开始---
声明:
- 文中内容收集整理自《C++ Primer 中文版 (第5版)》,版权归原书所有。
- 学习一门程序设计语言最好的方法就是练习编程
1、面向对象编程和泛型编程都是处理在编写程序时不知道类型的情况,不同之处在于,OOP能处理类型在程序运行之前都未知的情况,而在泛型编程中,在编译时就能获知类型了。
2、泛型编程与面向对象编程一样,都依赖于某种形式的多态性。面向对象编程中的多态性在运行时应用于存在继承关系的类。
3、在泛型编程中,我们所编写的类和函数能够多态地用于跨越编译时不相关的类型。一个类或一个函数可以用来操纵多种类型的对象。标准库中的容器、迭代器和是很好的泛型编程的例子。标准库用独立于类型的方式定义每个容器、迭代器和算法,因此几乎可以在任意类型上使用标准库的类和函数。
一、定义模板
1、重载函数:
1 int compare(const string &v1,const string &v2) 2 { 3 if (v1 < v2) 4 { 5 return -1; 6 } 7 else if (v1 > v2) 8 { 9 return 1; 10 } 11 12 return 0; 13 } 14 15 int compare(const double &v1,const double &v2) 16 { 17 if (v1 < v2) 18 { 19 return -1; 20 } 21 else if (v1 > v2) 22 { 23 return 1; 24 } 25 26 return 0; 27 }
唯一差异是参数的类型不同,函数体一样。
定义函数模板:。函数模板是一个独立于类型的函数,可以作为一种方式,产生函数的特定类型版本。
1 template2 int compare(const T &v1,const T &v2) 3 { 4 if (v1 < v2) 5 { 6 return -1; 7 } 8 else if (v1 > v2) 9 { 10 return 1; 11 } 12 13 return 0; 14 }
模板定义以关键字template开始,后跟一个模板参数列表。这是一个逗号分隔的一个或多个模板参数(template parameter)的列表,用<>包围。模板列表不能为空
2、当我们调用一个函数模板时,编译器使用函数实参来为我们推断模板实参。编译器用推断出的模板参数来为我们实例化一个特定版本的函数。
1 int main () 2 { 3 // 绑定到compare(const int&, const int&) 4 cout << compare(1, 0) << endl; 5 6 // 绑定到compare(const string&, const string&) 7 string s1 = "hi", s2 = "world"; 8 cout << compare(s1, s2) << endl; 9 return 0; 10 }
3、inline说明符放在模板形参表之后、返回类型之前,不能放在关键字template之前。
1 templateinline 2 int compare(const T &v1,const T &v2); //OK 3 4 inline template 5 int compare(const T &v1,const T &v2); //Error
4、模板程序应该尽量减少对实参类型的要求。
5、当编译器遇到一个模板定义时并不产生代码。只有实例化出模板的一个特定版本时,编译器才生成代码。当我们使用一个类类型对象时,类定义必须是可用的,但成员函数的定义不必已经出现。模板的头文件通常既包括声明也包括定义。函数模板和类模板成员的定义通常放在头文件中。
6、模板直到实例化的时候才产生代码,所以编译器只有在三个阶段报告错误:
一、编译模板本身时。
二、编译器遇到模板使用时。
三、模板实例化时。
7、类模板也是模板,因此必须以关键字template开头,后接模板形参表。
除了模板形参表外,类模板的定义看起来与任意其他类相似。在类和类成员的定义中,可以使用模板形参作为类型或值的占位符,在使用类时再提供那些类型或值。
与调用函数模板形成对比,使用类模板时,必须为模板形参显式指定实参:
8、
9、
二、模板实参推断
1、
2、
3、
三、重载与模板
1、
2、
3、
四、可变参数模板
1、
2、
3、
五、模板特例化
1、
2、
3、
---恢复内容结束---