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++(函数重载和函数模板)

一、函数重载

1、函数重载定义

??在C++中可以为两个或两个以上的函数提供相同的函数名称,只要参数类型不同,或参数类型相同而参数的个数不同, 称为函数重载

示例:

// my_max + 参数表
int my_max(int a,int b)
{
	return a > b ? a : b;
}
char my_max(char a,char b)
{
	return a > b ? a : b;
}
double my_max(double a,double b)
{
	return a > b ? a : b;
}
//每个同名函数的参数表是惟一,
int main()
{
	int ix = my_max(12,23);
	double dx = my_max(12.23,34.45);
	char chx = my_max('a','b');
	return 0;
}

2、判断函数重载的规则

  • 两个函数的参数表相同, 但是返回类型不同,会被标记为编译错误:函数的重复声明。

示例:

int my_max(int a,int b)
{
	return a > b ? a : b;
}
unsigned int my_max(int a,int b) // error;
{
	return a > b ? a : b;
}
int main()
{
	int ix = my_max(12,23);
	unsigned int = my_max(12,23); // error;
	reutrn 0;
}
  • 参数表的比较过程与形参名无关

示例:

// 声明同一个函数
int my_add(int a,int b);
int my_add(int x,int y);
  • 如果在两个函数的参数表中,只有缺省实参不同,则第二个声明被视为第一个的重复声明

示例:

void Print(int *br,int n);
void Print(int *br,int len = 10);
  • typedef 是数据类型的别名,如果两个函数参数表的区别旨在以一个使用了 typedef ,则该参数视为相同的参数列表。

示例:

typedef unsigned int u_int;
int Print(u_int a)
int Print(unsigned int b);
  • 当一个形参类型有 const 或 volatile 修饰时,如果形参是按值传递方式定义,在识别函数声明是否相同时,并不考虑 const 和 volatile 修饰符。

示例:

void fun(int a){ }
void fun(const int a) { }
  • 当一个形参类型有 const 或 volatile 修饰时,如果形参定义指针或引用时,在识别函数声明是否相同时,就要考虑 const 和 volatile 修饰符。

示例:

void fun(int *p) {}
void fun(const int *p) {}
void fun(int &a) {}
void fun(const int &a) {}
  • 注意函数调用的二义性,如果在两个函数的参数表中,形参类型相同,而形参个数不同,形参默认值将会影响函数的重载。
void fun(int a){}
void fun(int a,int b){}
void fun(int a ,int b = 10);

2、名字粉碎(名字修饰)

??“C”或者“C++”函数在内部(编译和链接)通过修饰名识别。修饰名是编译器在编译函数定义或者原型时生成的字符串。
??修饰名由函数名、类名、调用约定、返回类型、参数等共同决定。

  • 调用约定:

??_stdcall 是Pascal程序的缺省调用方式,通常用于Win32 Api中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。

??C调用约定(即用 _cdecl 关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。

??thiscall 仅仅应用于“ C++ ”类的成员函数。 this 指针存放于ECX 寄存器,参数从右到左压。thiscall 不是关键词,因此不能被程序员指定。

??在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预编译(预处理)、编译、汇编、链接。Name Mangling是一种在编译过程中,将函数名、变量名的名字重新命名的机制。

  • C 语言编译时函数名修饰约定规则

(1)C语言的名字修饰规则非常简单,_cdecl是C/C++的缺省调用方式, 调用约定函数名字前面添加了下划线前缀。
格式:_functionname
在这里插入图片描述
(2)_stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数。
格式:_functionname@number
在这里插入图片描述
(3)_fastcall 调用约定在输出函数名前加上一个“ @ ”符号,函数名后面也是一个“ @ ”符号和其参数的字节数
格式:@functionname@number
在这里插入图片描述

3、C++编译时函数名修饰约定规则:

_cdecl 调用约定:
1、以“?”标识函数名的开始,后跟函数名;
2、函数名后面以“@@YA”标识参数表的开始,后跟参数表;
3、参数表以代号表示:

  • X – void ,
  • D – char,
  • E – unsigned char,
  • F – short,
  • H – int,
  • I – unsigned int,
  • J – long,
  • K – unsigned long,
  • M – float,
  • N – double,
  • _N – bool,
  • PA-- 表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以“ 0 ”代替,一个“ 0 ”代表一次重复;

4、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;
5、参数表后以“@Z”标识整个名字的结束,如果该函数无参数,则以“ Z ”标识结束

//(?my_add_int@@YGHHH@Z)
int __stdcall my_add_int(int a, int b)
{
	return a + b;
}
int main()
{
	my_add_int(12, 23);
	return 0;
}

4、C++函数是重载

//(?my_max@@YAHHH@Z)
int my_max(int a, int b);
//(?my_max@@YADDD@Z)
char my_max(char a, char b);
//(?my_max@@YANNN@Z)
double my_max(double a, double b);
int main()
{
	my_max(12, 23);
	my_max('a', 'b');
	my_max(12.23, 34.45);
	return 0;
}

关键字 :
extern “C” : 函数名以C的方式修饰约定规则;
extern “C++” : 函数名以C++的方式修饰约定规则;

二、函数模板

??为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。

??函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,简化重载函数的设计。

函数模板定义如下:

template<模板参数表>
返回类型 函数名(形式参数表)
{
	...;//函数体
}

??<模板参数表>(template parameter list)尖括号中不能为空,参数可以有多个,用逗号分开。模板参数主要是模板类型参数。

??模板类型参数 (template type parameter) 代表一种类型 , 由关键字 class 或 typename ( 建议用typename) 后加一个标识符构成,在这里两个关键字的意义相同,它们表示后面的参数名代表一个潜在的内置或用户设计的类型。

示例:

template<class T>
T my_max(T a, T b)
{
	return a > b? a:b;
}
int main()
{
	my_max(12, 23);
	my_max('a', 'b');
	my_max(12.23, 34.45);
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-19 11:50:18  更:2022-05-19 11:50:20 
 
开发: 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年11日历 -2024/11/23 19:09:26-

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