类模板
一、简介
类模板和函数模板的定义及使用类似。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同。
- 类模板用于实现类所需数据的类型参数化
- 类模板在表示如数组、表、图等数据结构显得特别重要,这些数据结构的表示和算法不受所包含的数据类型的影响。
二、语法
C++ 中类模板的写法如下:
template <类型参数表>
class 类模板名{
成员函数和成员变量
};
类型参数表的写法如下:
class类塑参数1, class类型参数2, ...
类模板中的成员函数放到类模板定义外面写时的语法如下:
template <类型参数表>
返回值类型 类模板名<类型参数名列表>::成员函数名(参数表)
{
...
}
用类模板定义对象的写法如下:
类模板名<真实类型参数表> 对象名(构造函数实际参数表);
如果类模板有无参构造函数,那么也可以使用如下写法:
类模板名 <真实类型参数表> 对象名;
例:
template<class T>
class Person{
public:
Person(T id,T age){
this->mAge = age;
this->mId = id;
}
void Show(){
cout << "ID:" << mId << " Age:" << mAge << endl;
}
public:
T mId;
T mAge;
};
void main(){
//函数模板在调用的时候,可以自动类型推导
//类模板必须显式指定类型
Person<int> p(15,22);
p.Show();
}
三、类模板的派生
- 普通类派生类模板
- 类模板也可以派生类模板,这时,派生类模板的参数表中应包含基类模板的参数。
- 模板类与普通类一样也具有多继承,即模板类之间允许有多继承。
可以从类模板派生出新的类,既可以派生类模板,也可以派生非模板类。
//类模板派生普通类
template<class T>
class Person{
public:
Person(){
mAge = 0;
}
public:
T mAge;
};
//类区定义对象,这个对象需要编译分配内存,要指定类型
class SubPerson : public Person<int>{};
//类模板派生类模板
template<class T>
class Animal{
public:
void J(){
cout << mAge << "动物在叫!" << endl;
}
public:
T mAge;
};
template<class T>
class Cat : public Animal<T>{};
int main(void)
{
Cat<int> cat;//指定类型
return 0;
}
四、类模板外部实现成员函数
template<class T>
class Person{
public:
Person(T age, T id);
void Show();
private:
T mAge;
T mID;
};
//外部实现函数
template<class T>
Person<T>::Person(T age, T id){
this->mID = id;
this->mAge = age;
}
template<class T>
void Person<T>::Show(){
cout << "Age:" << mAge << " ID:" << mID << endl;
}
五、类模板的编译
首先,一个编译单元(translation unit)是指一个.cpp文件以及它所#include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件(假定我们的平台是win32),后者拥有PE(Portable Executable,即windows可执行文件)文件格式,并且本身包含的就已经是二进制码,但是不一定能够执行,因为并不保证其中一定有main函数。当编译器将一个工程里的所有.cpp文件以分离的方式编译完毕后,再由连接器(linker)进行连接成为一个.exe文件。
就像类一样,类模板是可以将其实现与声明放在一起的,或者也可以将接口与实现分离。但是呢,编译器由于历史原因对于分离式编译的支持非常弱,并且因平台的不同支持力度有所不同。
STL 的类模板都是接口与实现放在一起的,随着主流走就可以。(文件保存为类模板.hpp,其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再 将cpp加入到project中进行编译。)
六、类模板中的static关键字
不同的类型参数的类的静态成员变量是相互独立的,这是由类模板的实现机制决定的。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
template<class T>
class Person{
public:
static int a;
};
template<class T> int Person<T>::a = 0;//类外初始化
int main(void)
{
Person<int> p1, p2, p3;
Person<char> pp1, pp2, pp3;
p1.a = 10;
pp1.a = 100;
cout << p1.a << " " << p2.a << " " << p3.a << endl;//输出10 10 10
cout << pp1.a << " " << pp2.a << " " << pp3.a << endl;//输出100 100 100
return 0;
}
可以看到相同类型如int对应的类模板的对象之间的static成员是共享的,不同类型之间如int,float,char对应的类模板的对象之间的static是不共享的。