为什么需要类模板
类模板与函数模板的定义和使用类似,我们已经进行了介绍。 有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,如下面语句声明了一个类:
1 | //类模板由模板说明和类说明构成 |
类模板用于实现类所需数据的类型参数化
类模板在表示如数组、表、图等数据结构显得特别重要,这些数据结构的表示和算法不受所包含的元素类型的影响
单个类模板语法
1 | //类的类型参数化抽象的类 |
继承中的类模板语法
子类从模板类继承的时候,需要让编译器知道父类的数据类型具体是什么(数据类型的本质:固定大小内存块的别名)
1 |
|
知识体系
所有的类模板函数写在类的内部
所有的类模板函数写在类的外部,在一个cpp中
构造函数 没有问题
普通函数 没有问题
友元函数:用友元函数重载 << >>1
friend ostream& operator<< <T> (ostream &out, Complex<T> &c3) ;
友元函数:友元函数不是实现函数重载(非 << >>)
1)需要在类前增加类的前置声明函数的前置声明
1 |
|
2)类的内部声明必须写成:
1 | friend Complex<T> mySub <T> (Complex<T> &c1, Complex<T> &c2); |
3)友元函数实现必须写成
1 | template<typename T> |
4)友元函数调用 必须写成:
1 | Complex<int> c4 = mySub<int>(c1, c2); |
结论:友元函数只用来进行左移友移操作符重载。
所有的类模板函数写在类的外部,在不同的.h和.cpp中
也就是类模板函数说明和类模板实现分开
类模板函数
构造函数
普通成员函数
友元函数
用友元函数重载<<>>;
用友元函数重载非<< >>
要包含.cpp
总结
归纳以上的介绍,可以这样声明和使用类模板:
1) 先写出一个实际的类。由于其语义明确,含义清楚,一般不会出错。
2) 将此类中准备改变的类型名(如int要改变为float或char)改用一个自己指定的虚拟类型名(如上例中的numtype)。
3) 在类声明前面加入一行,格式为:
template
如:
template
class Compare
{…}; //类体
4) 用类模板定义对象时用以下形式:
类模板名<实际类型名> 对象名;
类模板名<实际类型名> 对象名(实参表列);
如:
Compare
Compare
5) 如果在类模板外定义成员函数,应写成类模板形式:
template
函数类型 类模板名<虚拟类型参数>::成员函数名(函数形参表列) {…}
关于类模板的几点说明:
1) 类模板的类型参数可以有一个或多个,每个类型前面都必须加class,如:
template
class someclass
{…};
在定义对象时分别代入实际的类型名,如:
someclass<int,double> obj;
2) 和使用类一样,使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象。
3) 模板可以有层次,一个类模板可以作为基类,派生出派生模板类。
1 |
|
继承中的类模板
1 |
|
类模板中的static关键字
1 |
|
类模板中的static关键字
从类模板实例化的每个模板类有自己的类模板数据成员,该模板类的所有对象共享一个static数据成员
和非模板类的static数据成员一样,模板类的static数据成员也应该在文件范围定义和初始化
每个模板类有自己的类模板的static数据成员副本
类模板在项目开发中的应用
小结
模板是C++类型参数化的多态工具。C++提供函数模板和类模板。
模板定义以模板说明开始。类属参数必须在模板定义中至少出现一次。
同一个类属参数可以用于多个模板。
类属参数可用于函数的参数类型、返回类型和声明函数中的变量。
模板由编译器根据实际数据类型实例化,生成可执行代码。实例化的函数。
模板称为模板函数;实例化的类模板称为模板类。
函数模板可以用多种方式重载。
类模板可以在类层次中使用 。