类模板 | |
类描述了对象(实例)是什么(有什么且能干什么) 所以,类是对象的设计图纸,对象是根据类这张设计图纸生产出来的具体产品 | |
比如,我们自定义一个栈的类,根据栈的定义,我们一般给到栈的最小操作集,包括 : 构造函数 、析构函数 、入栈 、出栈 、判空 、获取栈顶元素等;所以当定义一个栈对象时,这个栈对象只能调用类中定义的这些成员函数 | |
普通社畜可以拿工资以及年终奖,但 CEO 除了拿工资和年终奖,还能拿分红;所以 worker 类与 manager 类并不能抽象成一种类型 , | |
C++ 类模板 :
假如某些类具有相似的操作,则可以把这些类抽象成一组类;类模板就是描述了这些相似的类具有哪些相似的特征;如果说类是对象的设计图纸,那么类模板就是类的设计图纸;单个类描述了一个对象能做什么,而类模板描述了具有相同操作的类能做什么,感觉类模板特别适合用来描述容器;比如标准库中的 vector 以及其他容器类型;举例来说,vector 是动态数组,其元素类型可以是 int 也可以是 string ,甚至可以是用户自定义的类型;所以 vector 是一个类模板,描述了容器该有什么操作,如读取 、插入 、删除元素,这些操作是容器本身所支持的,与具体的元素类型无关,所以可以把元素类型 int 、string 、struct 都抽象为类型 T
C++ 函数模板 :
假如某些类型具有相似的操作,某个操作具有逻辑完全相同,只是操作对象的类型不同的多个版本,那么可以把这多个版本抽象成一个版本,这个版本忽略了对象的类型,统一用 T 来表示对象类型;
比如两个同类型的数比较大小,在 C 语言中,如果两个数是整数,就有一个整数比较函数,如果两个数是浮点数(float)则必须有一个 float 版本的比较函数,double 类型也必须有 double 版本的比较函数;这样显得很冗余,可以把 int 、float 、double 都抽象成类型 T ,只写逻辑过程,忽略类型;说到忽略类型,那就不得不提上面的,用类模板构建的容器了,这些忽略了类型的容器,也支持各种操作,一个操作就是一个函数,所以最好的方式就是用函数模板来定义这些类模板支持的操作(函数)
1. 引言和概述 | |
2. 一个简单的字符串模板 | 定义模板;模板实例化 |
3. 类型检查 | 类型等价;错误检测 |
4. 类模板成员 | 数据成员;成员函数;成员类型别名;static 成员; 成员类型;成员模板;友元 |
5. 函数模板 | 函数模板实参;函数模板实参推断;函数模板重载 |
6. 模板别名 | |
7. 源码组织 | 链接 |
8. 建议 | |
9. | |
引言
1. 模板支持将类型作为参数的程序设计方式,从而实现了对泛型程序设计的支持
2. C++ 模板机制允许在定义类 、函数 、类型别名时,将类型或值作为参数
一个简单的字符串模板
类型检查
类模板成员
类模板成员 | |
目录 | |
数据成员 | 1. 就像 "普通类" 一样,类模板可以有任意类型的数据成员 解释:类模板中的数据成员的类型不局限于 typename T 中的类型参数 T ,也可以是 int,float,char 或其他的用户自定义类型 |
2. 非 static 数据成员可以在其定义时初始化(类内初始值),也可以在构造函数中初始化 代码示例 : template<typename T> struct X { int m1 = 7;// 数据成员的类型不是只能为 T ,也可以是其他任意类型,类内初始化 T m2; X(const T& x) : m2{x} { } }; X<int> xi{9}; // T 被实例化为 int X<string> xs{"Rapperswil"}; // T 被实例化为 string | |
3. 非 static 数据成员可以是 const ,但不能是 constexpr | |
成员函数 | 4. 与 "普通类" 一样,非 static 成员函数的定义可以在类模板内部,也可以在外部 代码示例 : template<typename T> struct X { void mf1() { /* ... */ } // 类内定义 void mf2(); }; template<typename T> void X<T>::mf2() { /* ... */ } // 类外定义 |
5. 类模板的成员函数可以是 virtual 的,也可以不是 注意 : 6. 一个虚成员函数名,不能再用作一个成员函数模板名 | |
7. 可以使用 using 或 typedef ,向类模板引入成员类型别名 说明 :成员类型别名,在类模板的设计中起着非常重要的作用 | |
类型别名,定义了类的相关类型,定义的方式非常方便类外(代码)访问 | |
代码示例 :将容器的迭代器和元素类型指定为别名 template<typename T> class Vector { public: using value_type = T; using iterator = Vector_iter<T>; // Vector_iter 是在其他地方定义的 // ... }; | |