C++ 泛型程序设计(二): 类模板

类模板

背景:

定义一批相似的类
定义类模板
生成不同的类

在调用类模板时,指定参数,由编译系统根据参数提供的数据类型自动产生相应的模板类

类模板的定义

template <class 类型参数1, class 类型参数2, ...>
class 类模板名
{
	成员函数和成员变量;
};
  • 定义成员函数
template <类型参数表>
返回值类型 类模板名<类型参数名列表>::成员函数名(参数表)
{
  	...
}
  • 用类模板定义对象的写法:
类模板名 <真实类型参数表>  对象名(构造函数实际参数表);

如果类模板有无参构造函数,那么也可以只写为:

类模板名 <真实类型参数表> 对象名;

实例:Pair类模板

template <class T1, class T2>
class Pair {
    public:
        T1 key;
        T2 value;
        Pair(T1 k,T2 v):key(k),value(v){};//构造函数
        bool operator< (const Pair<T1,T2>&p) const;  
		//运算符重载,其传递的函数是一个Pair类型的一个指针的引用
		//const说明只是取比较大小,而不改变原来的值
};
template<class T1, class T2>
bool Pair<T1,T2>::operator<(const Pair<T1,T2>&p) const{ //Pair的成员函数,注意标记作用域
    return key < p.key;
}

int main() {
	Pair<string,int> student("Tom",19);
	//实例化出一个类,注意传入真实参数型列表
	//T1 被替换为string T2被替换为int
	//定义Pair类的student对象
	cout<<student.key<<" "<<student.value;
	return 0;
}

使用类模板声明对象

  • 编译器由类模板生成类的过程叫类模板的实例化,编译器自动用具体的数据类型替换类模板中的类型参数,生成模板类的代码
  • 由类模板实例化得到的类叫模板类,
  • 为类型参数指定的数据类型不同, 得到的模板类不同
  • 同一个类模板的两个模板类是不兼容的,即便其源于同一个类模板,如下列所示:
Pair<string,int> *p;
Pair<string, double> a;
p = &a; //wrong

函数模板作为类模板成员

#include <iostream>
using namespace std;

template <class T>
class A
{
public:
  	template<class T2>  
	// 函数模板不能和类模板的的参数相同!
	// 否则报错:declaration of class X shadows template parm class X
    void Func(T2 t)  
    {
      	cout << t;
    } 	//成员函数模板
};

int main()
{
  	A<int> a;
  	a.Func('K'); //成员函数模板 Func被实例化;T2 对应char
  	return 0;
}

类模板与非类型参数

类模板的 <类型参数表>中可以出现非类型参数:

  • 非类型参数:用来说明类模板中的属性
  • 类型参数:用来说明类模板中的属性类型,成员操作的参数类型和返回值类型
template <class T, int size>
class CArray
{
	T  array[size];
	//用非参数类型int size来标记array的大小,是一个固定的属性
public:
  	void Print()
    {
      	for(int i = 0; i < size; ++i)
          	cout << array[i] << endl;
    }
}; 

类模板与继承

通常而言,一共有四种方式:

  • 类模板派生出类模板
  • 模板类(即类模板中类型/非类型参数实例化后的类)派生出类模板
  • 普通类派生出类模板
  • 模板类派生出普通类

下面我们分别对上述几种方式结合例子加以说明:

  • 类模板派生出类模板
template <class T1, class T2>
class A {
  	T1 v1;
  	T2 v2;
};

template <class T1, class T2>
class B : public A<T2, T1>  {
	T1 v3;
	T2 v4;
};

template <class T>
class C : public B<T, T> {
  	T v5;
};

int main() {
	B<int,double> obj1; //T1替换为int,T2替换为double
	C<int> obj2;
	return 0;
}

在对B类进行实例化过程中,我们相当于调用了下述语句:

class B<int,double>:public A<double,int>{
	int v3; double v4;
};
class A<double, int> {
	double v1; int v2;
};
  • 从实例化后的模板类派生出类模板
template <class T1, class T2>
class A {
	T1 v1;
  	T2 v2;
};

class B : public A<int, double> {//对类模板实例化,变成模板类
	T v;
};
int main() {
	B<char>obj1;
	return 0;
}

此时,自动生成两个模板类:

A<int,double>
B<char>
  • 普通类派生出类模板
class A {
	int v1;
};

template <class T>
class B : public A {
	T v;
};
  • 模板类派生出普通类
template <class T>
class A {
	T v1;
  	int n;
};

class B :public A<int> {//模板类实例化作为父类
	double v;
};

References

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值