类模板

一、简介

类模板和函数模板的定义及使用类似。有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同。

  • 类模板用于实现类所需数据的类型参数化
  • 类模板在表示如数组、表、图等数据结构显得特别重要,这些数据结构的表示和算法不受所包含的数据类型的影响。

二、语法

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();
}

三、类模板的派生

  1. 普通类派生类模板
  2. 类模板也可以派生类模板,这时,派生类模板的参数表中应包含基类模板的参数。
  3. 模板类与普通类一样也具有多继承,即模板类之间允许有多继承。

可以从类模板派生出新的类,既可以派生类模板,也可以派生非模板类。

//类模板派生普通类
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),后者拥有PEPortable 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是不共享的。

posted @ 2021-01-05 22:57  东南亚季风  阅读(148)  评论(0编辑  收藏  举报