C++模板

目录

c++模板

一、什么是c++的模板

二、模板的概念

三、函数模板

(1)什么是函数模板

(2)函数模板的定义格式

(3)案例

(4)函数模板的实例化 

          a.实例化

          b.显式实例化

(5)函数模板的重载

(6)使用函数模板要注意的问题

四、类模板

1、定义类模板的格式

2、类与类模板的关系

3、类模板的实例化

(1)使用类模板创建对象时,必须指明具体的数据类型。

(2)当类模板有两个模板形参时,创建对象时,类型之间要用逗号分隔开。

(3)可以使用对象指针的方式来实例化

 

一、什么是c++的模板

程序设计中经常会用到一些程序实体:它们的实现和所完成的功能基本相同,不同的仅 仅是所涉及的数据类型不同。而模板正是一种专门处理不同数据类型的机制。

模板是泛型程序设计的基础(泛型generic type——通用类型之意)。

二、模板的概念

值和类型是数据的两个主要特征,它们在C++中都可以被参数化。

数据的值可以通过函数参数传递,在函数定义时数据的值是未知的,只有等到函数调用 时接收了实参才能确定其值。——这就是值的参数化。

数据的类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当函数 调用时,编译器根据传入的实参自动推断数据类型。——这就是类型的参数化(把类型 定义为参数)

带有类型参数的一段代码,实际上代表了一类代码,可以实现代码的复用,常用模板来 实现。

模板——是一段带有类型参数的程序代码,可以通过给这些参数提供一些类型来得到针 对不同类型的具体代码。
在C++中,能带有类型参数的代码可以是函数和类,所以模板一般分为函数模板和类模 板。

 

三、函数模板

(1)什么是函数模板

函数模板——实际上是定义一个通用函数,它所用到的数据的类型(包括返回值类 型、形参类型、局部变量类型)均被作为参数:不指定具体类型,而是用一个虚拟 的类型来代替(实际上是用一个标识符来占位)。凡是函数体相同的函数都可以用 这个模板来代替,在函数调用时根据传入的实参来逆推出真正的类型。这个通用函 数就称为函数模板。
 

(2)函数模板的定义格式

template <typename 形参名, typename 形参名...>     //模板头(模板说明)

返回值类型  函数名(参数列表)                   //函数定义

{

        函数体;

}

注意注意:

1,template是声明模板的关键字,告诉编译器开始泛型编程。

2,尖括号<>中的typename是定义形参的关键字,用来说明其后的形参名为类型 参数,(模板形参)。Typename(建议用)可以用class关键字代替,两者没有区别。

3,模板形参(类属参数)不能为空(俗成约定用一个大写英文字母表示),且在函 数定义部分的参数列表中至少出现一次。与函数形参类似,可以用在函数定义的各 个位置:返回值、形参列表和函数体。

4,函数定义部分:与普通函数定义方式相同,只是参数列表中的数据类型要使用 尖括,号<>中的模板形参名来说明。当然也可以使用一般的类型参数。
 

(3)案例

用函数模板实现多种类型数据的相加

#include <iostream>
using namespace std;
template<typename T>//模板头,template关键字告诉编译器开始泛型编程
T add(T t1, T t2)//类型参数化为T
{
	return t1 + t2;
}
int main()
{
	cout << add(12, 34) << endl;
	cout << add(12.2,45.6) << endl;
	return 0;
}

输出结果:

46
 
57.8 

 

当调用add()函数传入int型参数12和参数34时,形参T被替换成int,得到结果 为46

当传入float型参数12.2和参数45.6时,形参T被替换成float,得到结果为57.8

避免了为int型定义一个求和函数,再为float型定义一个求和函数,实现了代码 复用。

(4)函数模板的实例化

函数模板实例化的方法有两种:

隐式实例化:根据具体的函数调用形式,推演出模板参数类型。

显式实例化:通过显式声明形式指定模板参数类型

(1)隐式实例化


根据函数调用时传入的数据类型,推演出模板形参类型。模板形参的类型是隐 式确定的。

比如上面的多种类型相加

第一次调用add()函数模板:add(12,34),

①编译器根据传入的实参(12和34—>int型),推演出模板形参类型是int

②会将函数模板实例化出一个int类型的函数:

int add(int t1, int t2)

{

        return t1 + t2;

}

③生成int类型的函数后,再将实参12和34传入进行运算。

第二次调用add()函数模板:add(12.2, 45.6)

实参为float类型的数据,编译器先将模板实例化为如下模板函数后,再将实 参12.2和45.6传入进行运算:

float add(float t1, float t2)

{

        return t1 + t2;

}

 

(2)显式实例化

 

template 函数返回值类型 函数名<实例化的类型>(参数列表);

注意:这是声明语句,要以分号结束,<>中是显式实例的数据类型,即要实例 化出一个什么类型的函数。如:显示实例化为int,则在调用时,不是int 类 型的数据会 转换为int类型进行计算。

(5)函数模板的重载

前面学习过函数的重载。而函数模板可以用来创建一个通用功能的函数,以支持多 种不同形参,不同类型的参数调用,就产生一系列重载函数。

比如定义一个两个数相加的模板
根据传入参数不同,会实例化出不同的函数,比如

template<typename T>

T add(T t1, T t2)

{

        return t1 + t2;

}

 (6)使用函数模板要注意的问题

函数模板中的每一个类型参数在函数参数表中必须至少使用一次。例如:下 面的函数模板声明是不正确的:函数模板声明了两个参数T1与T2,但在使用 时 只使用了T1,没使用T2。

在全局域中声明的与模板参数同名的对象、函数或类型,在函数模板中将被 隐藏。例如:在函数体内访问num是访问的T类型的num,而不是全局变量num 

int num;

template <typename T>

void func(T t)

{

     T num;

}


  四、类模板 

1、定义类模板的格式

template<typename 形参名,typename 形参名…>

class 类名

{

        ………

}

注意:

说明:

(1)类模板中的关键字含义与函数模板相同。

(2)类模板中的类型参数可用在类声明和类实现中。类模板的模板形参(类型参 数)不能为空,一旦声明了类模板就可以用类模板的形参名声明类中的成员变量和 成员函数,即在类中使用内置数据类型的地方都可以使用模板形参名来代替。

template<typename T>   //这里不能有分号。一个模板形参

class A

{

public:

        T a;   //成员变量

        T b;   //成员变量

        T func(T a, T b);  //成员函数声明

};

 2、类与类模板的关系

 由于类模板包含类型参数,因此也称为参数化类,如果说类是对象的抽象,对象是 类的实例,则类模板是类的抽象,类是类模板的实例。

3、类模板的实例化

定义了类模板后就要使用类模板创建对象以及实现类中的成员函数,这个过程其实 也是类模板实例化的过程,实例化出的具体类称为模板类。

(1)使用类模板创建对象时,必须指明具体的数据类型。
例如:用上述定义的模板类A创建对象,则在类A后面跟<>,并在里面表明相应 的类型:

A<int>  a;    //类A中凡是用到模板形参的地方都会被int类型所代替

强调:与函数模板不同的是,类模板在实例化时,必须在尖括号中为模板形参显式 地指明数据类型(实参),编译器不能根据给定的数据推演出数据类型。即:不存 在将整型值10推演为int类型传递给模板形参的实参推演过程,必须要在<>中指 定int类型。
 

(2)当类模板有两个模板形参时,创建对象时,类型之间要用逗号分隔开。

(3)可以使用对象指针的方式来实例化

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值