深入浅出理解:函数模板与类模板、存在的实际意义以及使用方法,

原创 2015年11月17日 18:40:12

在讲模板之前,先闲扯一下吧:C++最重要的特性之一就是,代码的重用,为了实现代码重用,代码就必须具有通用性

通用代码不受数据类型的影响,并且可以自动适应数据类型的变化,这种程序设计类型称为参数化程序设计

模板是C++支持参数化程序设计的工具,通过它可以实现参数化多态性。

所谓参数化多态性是指:将程序所处理的对象的类型参数化,使得一段程序可以处理多种不同类型的对象。

简单的理解,模板就是为了让代码的通用性更强。有了以上的理解, 下面理解函数模板和类模板就轻松多了。

(2)函数模板

  要讲函数模板,就得先讲一讲函数重载,相信大家都知道,函数重载通常是对于不同的数据类型完成类似的操作。

在很多时候,一个算法其实是可以处理多种数据类型的。但是用函数实现算法时,即使设计为重载函数也只是

使用相同的函数名,函数体仍然要分别定义。下面举一个求绝对值的函数重载的实例,方便大家理解。

int abs(int x)

{

return x<0?-x:x;

}

double abs(double x)

{

return x<0?-x:x;

}

可以看出,这两个函数的功能和函数体是一模一样的,但是为了实现对不同数据类型的数据求绝对值操作,我们不得不写两个

同名函数来实现操作,如果能写一段通用代码适用与多种不同数据类型该多好呢,这会使代码的可重用性大大提高,从而提高

软件的开发效率。所以聪明的人们便设计出了这么一个工具,那就是函数模板,程序员只需对函数模板编写一次,然后基于调

用函数时提供的参数类型,C++编译器将自动产生相应的函数来正确处理该类型的数据。

函数模板的定义形式如下:

template<模板参数列表>

类型名  函数名(参数列表)

{

函数体的定义;

}

说明:class或者typename标识符,指明可以接收一个类型参数,这些类型参数代表的是类型,可以是系统预定义的数据类型,也

可以是自定义类型。类型参数可以用来指定函数模板本身的形参类型、返回值类型,以及声明函数中的局部变量。

下面举一个求绝对值的函数模板的程序。

#include<iostream>

using namespace std;

template<typename T>

T  abs(T x)

{

return x<0?-x:x;

}

int  main()

{

int n_number=-5;

double d_number=-5.5;

cout<<abs(n_number)<<ebdl;

cout<<abs(d_number)<<endl;

return 0;

}

运行结果如下:


在main函数中两次调用abs()函数,

对于调用表达式abs(n_number)时,由于n_number为int类型,所以推导出模板中类型参数T为int;

当调用表达式abs(d_number)时,由于d_number为double类型,所以推导出模板类型参数T为double;

当类型参数的含义确定后,编译器将以函数模板作为一个样板,生成一个函数,这一过程便是传说中的函数模板实例化;

其实编译器会实例化以下两个函数:

int abs(int x)

{

return x<0?-x:x;

}

double  abs(double x)

{

return x<0?-x:x;

}

下面来一个稍微复杂一点的函数模板的例子,供各位深入理解一下函数模板的用法。

#include<iostream>

using namespace  std;

template<class T>

void outputArray(const T *array,int count)

{

for(int i=0;i<count;i++)

{

cout<<array[i]<<" ";

}

cout<<endl;

}

int main()

{

const  int  a_count=8,b_count=8,c_count=20;

int    a[a_count]={1,2,3,4,5,6,7,8};

double    b[b_count]={1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8};

char   c[c_count]="Welcome to see you!";

cout<<"数组a:"<<endl;

outputArray(a,a_count);

cout<<"数组b:"<<endl;

outputArray(b,b_count);

cout<<"数组c:"<<endl;

outputArray(c,c_count);

return 0;

}

运行效果如下图:



(3)类模板

类模板可以使用户为类定义一种模式,使得类中的某些数据成员、成员函数、返回值或者局部

变量能取任意类型。(包括系统预定义和用户自定义的)

如果说类是对一组对象公共性质的抽象,而类模板则是对不同类的公共性质的抽象,所以说类模板是更高层次的抽象。

类模板声明的语法形式:

template<模板参数表>

class  类名

{

类成员声明;

}

其中类成员的声明方法与普通类的声明方法其实是一模一样的,只是它的各个成员(数据成员和函数成员)通常要用到模板的类型参数T;

注意:如果要在类模板以外定义成员函数,要采用以下形式

template <模板参数表>

类型名  类名<模板参数标识符列表>::函数名(参数表)

一个类模板声明,它自身并不是一个类,它说明类的一个家族,只有当它被其它代码引用时,模板才根据需要生成具体的类。

使用一个模板类来建立对象时,格式如下:

模板名<模板参数表>对象名1,....对象名N;

下面举个例子,方便大家理解,

本例中,声明一个实现任意类型数据存取的类模板Store,然后通过具体数据类型参数对类模板进行实例化,

生成类,然后类再被实例化,

生成对象s1,s2,s3,d.

源程序如下:

#include<iostream>
#include<cstdlib>
using namespace  std;

struct Student
{
	int id;
	float gpa;
};
template<class T>
class Store
{
	private:
		T item;
		bool haveValue;
	public:
		Store();
		T& getElem();
		void putElem(const T &x);			
};
template<class T>
Store<T>::Store():haveValue(false){}

template<class T>
T& Store<T>::getElem()
{
	if(!haveValue)
	{
		cout<<"没有数据"<<endl;
		exit(1); 
	}
	return item;
}

template<class T>
void Store<T>::putElem(const T &x)
{
	haveValue=true;
	item=x;
}

int main()
{
	Store<int>  s1,s2;
	s1.putElem(3);
	s2.putElem(-7);
	cout<<s1.getElem()<<"  "<<s2.getElem()<<endl;

	Student g={101011,99};
	Store<Student>s3;
	s3.putElem(g);
	cout<<"The student ID is:  "<<s3.getElem().id<<endl;
	
	Store<double>d;
	cout<<d.getElem()<<endl;
		
	return 0;
}
运行结果:



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

模板——函数模板与类模板

模板(template)是一个将数据类型参数化的工具。模板分为函数模板和类模板两种。 在定义模板的时候不说明某些函数参数或者数据成员的类型,而将它们的数据类型作为模板参数。在使用模板时根据实参的...

C++模板:函数模板、类模板、模板与继承

C++模板:描述             C++提供一种模板的机制来减少代码重复。比如:对于同一样函数使用不同的数据类型,int,double,char等。C++模板属于“元编程”的范畴。 C++ 模...

函数模板与类模板的区别

函数模板与类模板有什么区别?答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化 必 须由程序员在程序中显式地指定。 即函数模板允许隐式调用和显式调用而类模板只能显示调用...
  • csw_100
  • csw_100
  • 2010年08月27日 20:35
  • 10419

C++模板的理解与使用

最近发现原来学的东西根本都不理解,所以本人正在恶补C++,把自己对C++中概念的最简单粗暴的理解写下来。 有问题的地方还请指出~随时更正 模板:顾名思义,就是为了方便以后使用而出现的东西,生活中的...

一个HR人给应届生的面试建议,关于应届生面试自我介绍、常见问题及回答、面试礼仪、技巧等,非常全面、非常专业,面试前必看,晚了后悔呀。

一个HR人给应届生的面试建议,关于应届生面试自我介绍、常见问题及回答、面试礼仪、技巧等,非常全面、非常专业,面试前必看,晚了后悔呀。 从事人力资源工作很多年了,多多少少积累了一些经验。已经有许多同仁...
  • xlh1991
  • xlh1991
  • 2014年11月27日 20:14
  • 1308

模板——函数模板与类模板

模板(template)是一个将数据类型参数化的工具。模板分为函数模板和类模板两种。 在定义模板的时候不说明某些函数参数或者数据成员的类型,而将它们的数据类型作为模板参数。在使用模板时根据实参的...

理解双绞线中直通线、交叉线的实际意义

一、什么是双绞线 LAN网络中最常见的数据传输铜介质是双绞线。铜介质优点是可以非常好的传导电信号,缺点是易受外界干扰而产生畸形和信号衰减,导致长距离传输过程中能量损失。为解决上述不足,提高数据传输稳...

委托类型协变和逆变的实际意义

设一个委托 TypeA1 DelegateDefine(TypeB1 b)和实际调用的委托方法TypeA2 DelegateInstance(TypeB2 b){}根据面向对象继承使用的原则,Dele...

特征值和特征向量的实际意义

本文转自知乎大牛。 从定义出发,Ax=cx:A为矩阵,c为特征值,x为特征向量。 矩阵A乘以x表示,对向量x进行一次转换(旋转或拉伸)(是一种线性转换),而该转换的效果为常数c乘以向量x(即只进行...

Redis集群~windows下搭建Sentinel环境及它对主从模式的实际意义

回到目录 关于redis-sentinel出现的原因 Redis集群的主从模式有个最大的弊端,就是当主master挂了之前,它的slave从服务器无法提升为主,而在redis-sentin...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入浅出理解:函数模板与类模板、存在的实际意义以及使用方法,
举报原因:
原因补充:

(最多只允许输入30个字)