C++入门学习——模板

为什么需要模板?

我们已经学过重载(Overloading),对重载函数而言,C++ 通过函数参数(参数个数、参数类型)的正确匹配来调用重载函数。例如,为求两个数的最大值,我们定义 max () 函数需要对不同的数据类型分别定义不同重载(Overload)版本。

//函数1
int max(int x, int y);
{
	return(x>y)?x:y ;
}

//函数2
float max( float x, float y)
{
	return (x>y)?x:y ;
}

//函数3
double max(double x, double y)
{
	return (c>y)?x:y ;
}

现在,我们再重新审视上述的 max() 函数,它们都具有同样的功能,即求两个数的最大值,能否只写一套代码解决这个问题呢?这样就会避免因重载函数定义不全面而带来的调用错误(如,我们分别定义了 char a,b; 那么在执行 max(a,b) 时 程序就会出错,因为我们没有定义char 类型的重载版本)。

同样的,对于类而言,也存在同样的问题(基本上是重复性的工作):

//对两个整数作比较
class Compare_int
{
public:
	Compare(int a,int b){x=a;y=b;}
	int max( ) {return(x>y)?x:y;}
	int min( ) {return(x<y)?x:y;}
private:
	int x,y;
};

//对两个浮点数作比较
class Compare_float
{
public:
	Compare(float a,float b) {x=a;y=b;}
	float max( ) {return(x>y)?x:y;}
	float min( ) {return(x<y)?x:y;}
private:
	float x,y;
}

为解决上述问题 C++ 引入模板机制:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。

函数模板

函数模板的一般形式如下:

template <class 形参名, class 形参名, ……> 返回类型 函数名(形参表)

{

//函数定义体

}

其中 template 和 class 是关键字,class 可以用 typename 代替,在这里 typename 和 class 没区别,<> 括号中的参数叫模板形参,模板形参和函数形参很相像,模板形参不能为空。

一但声明了类模板,函数中使用内置类型的地方都可以使用模板形参名来声明。模板形参需要调用该模板函数时提供的模板实参来初始化模板形参,一旦编译器确定了实际的模板实参类型就称他实例化了函数模板的一个实例。

template <class T> void swap(T& a, T& b)
{
	//……
}

当调用这样的模板函数时类型 T 就会被被调用时的类型所代替,比如 swap(a,b) 其中 a 和 b 是 int  型,这时模板函数 swap 中的形参 T 就会被 int 所代替,模板函数就变为 swap(int &a, int &b)。而当 swap(c,d) 其中 c 和 d 是 double 类型时,模板函数会被替换为swap(double &a, double &b),这样就实现了函数的实现与类型无关的代码。

示例代码如下:

#include <iostream>
using std::cout;
using std::endl;

//声明一个函数模版,用来比较输入的两个相同数据类型的参数的大小,
//class也可以被typename代替,
//T可以被任何字母或者数字代替。

//template <typename T>
template <class T> T max(T x,T y)
{
	return(x>y)?x:y;
}

int main()
{

    int a=2, b=10;
    cout<< "较大整数:"<<max(a, b)<<endl;

	double m=1.5, n=5.6;
    cout<< "较大实数:"<<max(m, n)<<endl;

	return 0;
}

运行结果如下:

类模板

类模板的一般形式如下:

template <class 形参名, class 形参名, ……>   class 类名

{

//类定义...

};

一但声明了类模板就可以用类模板的形参名声明类中的成员变量和成员函数,即可以在类中使用内置类型的地方都可以使用模板形参名来声明。比如:

template <class T> class A
{
public:
	T a;
	T b;
	T hy(T c, T &d);
};

在类 A 中声明了两个类型为T的成员变量 a 和 b,还声明了一个返回类型为 T 带两个参数类型为 T 的函数 hy。

类模板对象的创建:比如一个模板类 A,则使用类模板创建对象的方法为 A<int> m;在类 A 后面跟上一个 <> 尖括号并在里面填上相应的类型,这样的话类 A 中凡是用到模板形参的地方都会被 int  所代替。当类模板有两个模板形参时创建对象的方法为 A<int, double> m;类型之间用逗号隔开。

在类模板外部定义成员函数的方法为:

template<模板形参列表> 函数返回类型 类名<模板形参名>::函数名(参数列表){函数体}

比如有两个模板形参 T1,T2 的类 A 中含有一个 void h() 函数,则定义该函数的语法为:

template<class T1, class T2> class A
{
public:
	void h();
};

template<class T1,class T2> void A<T1,T2>::h()
{
	// ……
}

注意:模板的声明或定义只能在全局,命名空间或类范围内进行。即不能在局部范围,函数内进行,比如不能在 main() 函数中声明或定义一个模板。

示例代码如下:

#include <iostream>
using namespace std;

template <class numtype> class Compare //类模板
{
public:
	//Compare(numtype a,numtype b){x=a;y=b;}
	Compare(numtype a,numtype b);
	numtype max(){return (x>y)?x:y;}
	numtype min(){return (x<y)?x:y;}
private:
	numtype x,y;
};

template <class numtype> Compare<numtype>::Compare(numtype a,numtype b)
{
	x=a;
	y=b;
}

int main( )
{
	Compare<int>cmp1(3,7); //定义对象cmp1,用于两个整数的比较
	cout << cmp1.max() << " is the Maximum" << endl;
	cout << cmp1.min() << " is the Minimum" << endl << endl;

	Compare<float> cmp2(45.78,93.6); //定义对象cmp2,用于两个浮点数的比较
	cout << cmp2.max() << " is the Maximum" <<endl;
	cout << cmp2.min() << " is the Minimum" <<endl<<endl;

	Compare<char> cmp3('a', 'A'); //定义对象cmp3,用于两个字符的比较
	cout << cmp3.max() << " is the Maximum" <<endl;
	cout << cmp3.min() << " is the Minimum" <<endl;

	return 0;
}

运行结果如下:

本教程示例代码下载请点此处。

参考资料:

http://www.cnblogs.com/gw811

http://www.cnblogs.com/gaojun

时间: 2024-08-07 17:58:08

C++入门学习——模板的相关文章

JavaSE入门学习21:Java面向对象之接口(interface)(二)

一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.java源文件代码: public class Test{ public static void main(String[] args){ //实现接口Singer Singer s1 = new Student("Amy"); s1.sing(); s1.sleep(); s1.study

OpenGL入门学习

说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色来做吗?显然是不行的. 本帖的目的是让大家放弃TC的老旧图形接口,让大家接触一些新事物. OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX更优越的特性. 1.与C语言紧密结合. OpenGL命令最初就是用C语言函数来进行描述的,对于学习过C语言的人来讲,OpenGL是容易理解和学习的

Surveillance Monitering入门学习论文笔记(一)

本科毕业设计需要,最近开始进行Surveillance Monitering的入门学习.对看过的论文进行一些摘录和整理,一方面方便自己勘察,另一方面可以与大家进行交流学习.由于水平.基础有限,希望大家不吝赐教,谢谢~ 论文来自: [1]胡琼,秦磊,黄庆明. 基于视觉的人体动作识别综述[J]. 计算机学报,2013,12:2512-2524. ******************************************************* 部分内容为网上摘录,由于时间有限未能列出所有

ReactJS入门学习一

阅读目录 React是什么? React如何制作组件? 理解组件属性props 理解页面中如何渲染数据的 理解从服务器端获取数据及理解state的 回到顶部 React是什么? React仅仅是VIEW层,而我们经常看到Angular是一个完整的框架,而React不是,因此我们看到他们两个的侧重点不一样,所以也不能比较的,React提供了模板语法及一些函数钩子用于HTML的渲染,只用于View层. React的优点?       1. 虚拟DOM 在DOM树的状态发生改变时,虚拟DOM机制会将前

Asp.Net MVC5入门学习系列③

添加一个视图(View) 接着上篇的入门系列,上面解说添加一个简单Controller(控制器),这里我们简单的在来添加一个View(视图)来展示我们Controller里执行完(Action)动作/方法后的结果. 我们修改我们的HelloWorldController到默认创建的代码,如下: 然后我们在Views/HelloWorld文件夹里来添加一个Index的视图,在添加的时候我们选择使用模版,具体操作如下: 然后选择_Layout.cshtml作为我们的模板点击确定后项目结构如下. 简单

PHP入门学习:现在写 PHP,你应该知道这些

本文来源:http://www.zretc.com/technologyDetail/443.html 如果你正在进行PHP入门学习,那么下面这些关于PHP的入门知识你应该知道哦! 首先你应该是在用 PHP 5.3 以上的版本,如果 PHP 版本在这之下,是时候该升级了.如果有条件,最好使用最新的版本. 1.PSR 很多人以为 PSR 只是做一些规范代码风格等无关痛痒的事情,但其实远不止此. PSR 的一系列标准文档由 php-fig (PHP Framework Interop Group)起

OpenStack 入门学习之四:icehouse版本中Heat的简单介绍

Heat简介 Heat是OpenStack的负责编排计划的主要项目.它可以基于模板来实现云环境中资源的初始化,依赖关系处理,部署等基本操作,也可以解决自动收缩,负载均衡等高级特性.目前Heat自身的模板格式(HOT)正在不停的改进,同时也支持AWS CloudFormation 模板(CFN),HOT的目标是在不远的将来可以完全的替代CFN. Heat提供了一个OpenStack的原生REST API和CloudFormation兼容的查询API. Heat的工作原理 Heat主要是基于模板文件

Hibernate的核心API ---- 入门学习

叙:学习hibernate是必不可少的要了解其核心的API,下面电虫就核心API进行记录学习: Hibernate核心API Hibernate核心API有configuration.SessonFactory.Session.Transaction等,在Session中有增删改查等小地API,下面进行详细学习: 学习要有目标有方向,所以从一段代码中从上到下的进行研读不失为一种高效率的学习方法,学习模板代码如下所示: 1 package com.java.hibernate.demo1; 2 3

Retrofit 入门学习

Retrofit 入门学习官方RetrofitAPI 官方的一个例子 public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } 这些注解都有一个参数 value,用来配置其路径,比如示例中的 users/{user}/repos, 我们还注意到在构造 Retrofit