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

原创 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;
}
运行结果:



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

相关文章推荐

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

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

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

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

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

数学概念实际意义探究小记

声明:仅个人小记。前言:本文是对一些数学概念的物理或者其他实际意义的延伸,简要记录一些本人遇到的数学概念的实际意义,并不一定是,提供的解析值得思考或者便于理解,或者具有更好的实用价值。1. 行列式  ...

高等几何——讨论交比的实际意义

1 相关链接: 参考百度关于交比的解释:点击打开链接 2 定义: 交比(cross ratio) 射影几何学中基本的射影不变量之一。一般是用共线的四个点来定义的,亦称之为调和比。早在...

MyBatis的Cache实际意义不大

转载的一篇文章。 出于新项目一定要求要用jsp,让我这个习惯写窗体应用程序的去搞web开发,让我好生为难。半路出家,遇到问题很多,转载些文章,自己顺便修改些,留备忘。 说意义不大是在于: a、面...

C++ 类模板使用方法

1编译器如何处理模板 编译器遇到模板的实例化时,如Grid b,则为Spread编写另一个Grid类。会使用Spread代替模板定义中的所有的T,来编写Grid模板的Spread版的代码,有点类似宏...

C#集合篇,在业务背景下(***产品升级管理):依赖注入,变量声明,三元表达式,常用字符串相关操作方法,ADO.NET,EF机制,T4模板自动生成实体类,ref变量巧用,属性实际运用,唯一性验证

QQ:1187362408 欢迎技术交流和学习 关于系统产品升级报告管理,业务需求: TODO: 1,升级报告管理:依据各县区制定升级报告(关联sAreaCode,给每个地区观看具体升级报告信息...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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