IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++ 函数重载(多态)、函数模板 -> 正文阅读

[C++知识库]C++ 函数重载(多态)、函数模板

内容均出自《C++ primer plus》,本文仅为个人理解总结所用。
若有不明欢迎站内私信交流。
若发现文中错漏之处,期待不吝赐教站内私信。

(一)函数重载(多态)

先上定义:

C++ Premer Plus (page276)

  • 函数多态是C++在C语言的基础上新增的功能。
  • 术语"多态":指的是有多种形式。
  • 术语"函数重载":指的是可以有多个同名函数,因此对名称进行了重载。
  • 两个术语是同一回事,但通常使用函数重载。
  • 函数多态(函数重载)让程序能够使用多个同名的函数。

实例理解:

同名函数,程序如何区分需要使用哪个?
——根据特征标

  • 函数重载的关键是函数的参数列表——也称为特征标
  • 若参数数目/参数类型不同,则特征标也不同。
  • tips: const限定符、 &引用符不为特征标
//比如本组函数
void print(const char* str, int width);		//#1
void print(double d, int width);			//#2
void print(long l, int width);				//#3
void print(int i, int width);				//#4
void print(const char *str);				//#5

使用print( )函数时,编译器将根据所采用的的用法使用有相应特征标的原型:

printf("Pancakes", 15);						//自动匹配#1
printf("Syrup");							//自动匹配#5
printf(1999.0, 10);							//自动匹配#2
printf(1999, 12);							//自动匹配#4
printf(1999L, 15);							//自动匹配#3
  • tips: 特别注意:const限定符、 &引用符不为特征标

(二)函数模板

先上定义

函数模板是通用的函数描述,使用泛型来定义函数,其中的泛型可用具体的类型(如int 或 double)替换。
通过类型作为参数传给模板,可使编译器生成该类型的函数。

使用场景分析:

  • 假设我们需要交换两个int变量的值的函数,一般来说则直接撸:
void swap(int &a, int &b)
{
	int tmp;
	tmp = a;
	a = b;
	b = tmp;
}
  • 现在我们新增了需求,要求增加一个交换double变量的值的函数,一般来说可以再加一个函数:
void swap(double &a, double &b)
{
	double tmp;
	tmp = a;
	a = b;
	b = tmp;
}
  • 那如果需求又增加了呢?要求char,short,float,long都来一套?
  • 方法一:都来一套也行。
  • 方法二:
    它们做一模一样的事情,只是参数类型不同
    C++允许以任意类型的方式来定义函数:函数模板;

函数模板建立

template <typename AnyType>				//紫色字体:关键字  黑色字体:类型名称
void swap(AnyType &a, AnyType &b)
{
	AnyType tmp;
	tmp = a;
	a = b;
	b = tmp;
}

对,就这么简单,这就是泛型基本概念。

Tips:

  • 模板并不创建函数,而只是告诉编译器如何定义函数。
  • 需要交换int数据时,编译器将按模板模式创建这样的函数,并用int 代替 AnyType。(实例化/隐式实例化)
  • 同样,需要交换double 时,编译器将按模板模式创建这样的函数,并用double代替 AnyType。
  • C++98 添加关键字typename之前,C++使用关键字class来创建模板。
template <class AnyType>
void swap(AnyType &a, AnyType &b)
{
	AnyType tmp;
	tmp = a;
	a = b;
	b = tmp;
}

模板显示实例化声明

建立模板之后,发现我其实只需要用short 和 int 两种,那我直接告诉编译器我需要这两个。
隐式实例化:声明模板,编译器自动创建
显示实例化: 声明模板,告诉编译器通过模板创建我需要的类型。
区别:隐式实例化,编译器发现函数需要使用,才创建实例。 显示实例化,不管有没有使用都创建实例。

//建立函数模板
template <typename AnyType>				//紫色字体:关键字  黑色字体:类型名称
void swap(AnyType &a, AnyType &b)
{
	AnyType tmp;
	tmp = a;
	a = b;
	b = tmp;
}
//声明即可,编译器会创建int实例
template void swap<int>(int, int);


(三)重载的模板

简单示例笔记

template <typename AnyType>					//#1
void swap(AnyType &a, AnyType &b)			//模板 + 特征标为两个引用变量
{
	AnyType tmp;
	tmp = a;
	a = b;
	b = tmp;
}

template <typename AnyType>					//#2
void swap(AnyType a[], AnyType b[], int n)	//模板 + 特征标为两个数组、一个整型
{
	AnyType tmp;
	int i;
	for(i = 0; i< n; i++){
		tmp = a[i];
		a[i] = b[i];
		b[i] = tmp;
	}
}

(四)模板具体化

理解完重载和模板函数之后,如果还不晕的话。
那么,继续。

假设有个需求:
众所周知,结构体是可以直接赋值的。
但是我只想交换结构体里面salary, floor 两个变量值
因此我希望调用swap如果传入的是job(指定类型)的话,执行指定处理

struct job
{
	char name;				//姓名
	double salary;			//薪资
	int floor;				//楼层
};

template <> void swap<job>(job &j1, job &j2)		//模板具体化
{
	double salary;
	salary = j1.salary;
	j1.salary = j2.salary;
	j2.salary = j1.salary;

	int floor;
	floor = j1.floor;
	j1.floor = j2.floor;
	j2.floor = j1.floor;	
}

(五)要点总结

  • 重载:同名函数,根据特征标(参数数目/参数类型)不同而匹配不同的处理函数。
  • const限定符、&引用符,不计入特征标。
  • 模板:定义函数模板,编译器生成对应不同数据类型相同操作函数实例。
  • 隐式实例化:定义模板,编译器自动创建
  • 显示实例化: 定义模板,手动告诉编译器该创建哪个类型。
  • 可重载模板 = 重载 + 模板
  • 具体化:不使用模板生成函数,定义一个指定具体类型的全新函数。
  • 区分实例化和具体化
    实例化:使用模板,只需要声明,编译器就会生成指定类型的实例。
    具体化:不使用模板,需要再编写函数定义。

补充:

  • 以上均为同名函数,编译器会自动匹配,匹配规则十分细密,后续学习了以后再整理。
  • 也可以编写代码,引导编译器匹配我们希望它匹配的函数。
//单纯比较
template<typename T>			//#1
T lesser(T &a, T &b)
{
 return a < b? a : b;
}

//比较绝对值
int lesser( int a, int b)		//#2
{
 a = a< 0? -a : a;
 b = b< 0? -b : b;
return a < b? a : b;
}

int m = 20;
int n = -30;
double x = 15.5;
double y = 25.9;
函数调用方式编译器寻找匹配函数
lesser(m , n)int类型,匹配 int lesser( int a, int b)
lesser(x , y)double类型,匹配模板,并且生成double实例
lesser<>(m , n)int类型,但调用处增加<> ,匹配模板,并且生成int实例
lesser(m , n)int类型,但调用处增加<int> ,匹配模板,并且生成int实例
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-08 11:03:10  更:2021-08-08 11:07:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 22:00:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码