C++:2.4函数重载

目录

2.4.1预备知识:同名函数与一函多义

2.4.2,函数重载的概念

2.4.3,函数重载的格式

2.4.4,重载函数的调用端

       1一函多义

       1.1 可以进行无参调用,就跟含缺省参数的函数的无参调用一样

        2 隐式类型转换的冲突问题

2.4.5,函数重载与缺省参数

2.4.6 函数重载的意义

2.4.7函数重载实现的原因——函数名修饰规则的不同

2.4.7.1函数名修饰规则的使用场景

2.4.7.2 函数名修饰的规则和寻址的使用  

2.4.7.2.2  修饰的函数名寻址时的使用

 1生成符号表

 2查表的地址


2.4.1预备知识:同名函数与一函多义

        在了解函数重载之前,我们要知道函数重载是弥补C语言不兼容同名函数的情况,那么为啥会要求同名同名函数存在呢?且听我慢慢道来。

        我们在为函数命名时常用“功能冠以名”,不然不好凭名字知道其功能,这就可能会出现功能相近似的两个函数出现名字冲突这种情况,所以常常还会对起名字加上前缀后缀等,也就是改名字(详情参见:命名空间),当然我们之前学了命名空间,那能否解决这个问题呢?答案是可以的,但有使用条件,无论是使命名空间域降级的域展开,还是替换到全局域的指定展开,亦或是一次一个的指定访问,都是使的同名的多个函数每次只能使用固定的一个,即一个函数只能有一个作用,而调用重载的函数时是通过函数名符号表+形参类型+形参个数来寻址的,这就使得在同一个域中真正地存在同名函数,但要知道的是他们虽然同名但本质上是不同两个函数的,只是因为函数寻址方式的不同而存在,函数调用时先是按函数名找,后按参数类型找,只要调用时传不同的参数,就能实现——一函多义,多函合并。

        为什么要实现一函多义,多函合并呢?

        1.实现功能相近而参数不同的函数合并,能加强代码的可读性,降低函数使用成本,毕竟需要记得函数种类少了,用也少了吗。

        2.

2.4.2,函数重载的概念

        几个同名不同形参参数顺序的函数相互构成重载,彼此互称重载函数。可见这是一种关系。

        N×同名不同参数顺序的函数=>函数重载。

注意:形参顺序是指形参类型+个数组成一个有序的以类型为成员的数组。

          由于函数的寻址规则在C++中有所改变,当函数名和形参顺序同时向同是才发生命名冲突。

           为什么不能加上返回值类型作为区别依据呢?时间上在函数寻址就没有考虑返回值,当然也无法找到,这是因为函数调用时就没有返回值的要求,编译器通过函数调用所给的信息来寻址。

2.4.3,函数重载的格式

2.4.4,重载函数的调用端

       1一函多义

        重载函数在调用时在形式上看似是调用一个函数的,实质是调用多个,这就在函数的调用端,或者说应用端实现了一函多义。

     func函数看是能实现打印两个浮点型或整型,但那是只是两个函数调用的结果,这也说明了C++的实现层与应用层分离的更彻底。

       1.1 可以进行无参调用,就跟含缺省参数的函数的无参调用一样

        引入无形参的通同名函数实现重载。但不要这么做,详情见下文2.4.5。

        2 隐式类型转换的冲突问题

当调用函数传参数时,字符型与整型可以进行类型的相互转化,但前提是转化的方向是确定的,不然会因为转换方向的二义性产生冲突。

        隐式转换就只用一个方向

#include"nest.h"

//以下的函数使用一个就行,方向就在会只有一个
//void func(int a, int b )//半缺省时,缺省参数只能由右到左,否则不能部分传参调用
//{
//	cout << a << ',' << b << endl;
//	printf("\n");
//}

void func(double a,double b )
{
	cout << a << ',' << b << endl;
	printf("\n");
}

        转换方向有两个

#include"nest.h"

//两个函数构成重载,方向有两个
void func(int a , int b , int c )
{
	cout << a << endl << b << endl << c << endl << a + b + c << endl;
	printf("\n");
}

void func(int a, int b )//半缺省时,缺省参数只能由右到左,否则不能部分传参调用
{
	cout << a << ',' << b << endl;
	printf("\n");
}

void func(double a,double b )
{
	cout << a << ',' << b << endl;
	printf("\n");
}

2.4.5,函数重载与缺省参数

        已经构成重载关系的函数,在其中多个函数增加缺省参数后仍构成重载关系,但是没有实用价值,不要这么做,为什么呢?重载函数可以进行无参调用的(见上文,2.4.4),全缺省函数也可以,这就使得两者在功能,用法上产生重叠,进而使得不传参调用时产生二义性,调那个函数谁也不知道。

2.4.6 函数重载的意义

        合并成类的思想:功能相近的函数合并成一类函数。

2.4.7函数重载实现的原因——函数名修饰规则的不同

2.4.7.1函数名修饰规则的使用场景

        C++能实现重载而C语言不行就是因为两者的函数寻址规则不同,是按照修是好的函数名作为地址的代名词寻找函数以访问的 。

        这就涉及了编译连接过程:

1,预处理:拷贝+各.c文件拷贝份头文件展开,宏替换,条件编译,去注释生成 多个.i文件(C++代码)

//

2.   编译:各.i文件检查语法,生成汇编代码生成各.s文件(汇编指令代码)。报错就在这时候,只有执行到这时候才能反汇编,编译也是最复杂的,详情参见编译原理

        当要执行调函数的汇编指令时,需要call 函数的地址,但是函数会定义在(声明与定义分离实现应用层与实现层分离,便于分层管理)(也就是多文件才是)另一个.s文件所对应的内存上,这就使得当前阶段无法获取函数地址,当前程序处于阻塞状态,若有该函数的声明(担保人,CPU你执行吧,没事的(当然有无定义得看另一个.s文件,有没有我不管)),使用声明产生的函数名修饰规则而的字符串占据要接受地址的地方,就继续执行其他汇编指令。

3.    汇编:

       各.s文件转换成二进制指令码的.o文件。(编译器在此时产生符号表 )

4,链接:    

       各个.o文件合并+内部再未链接的链接(eg.函数按照 使用函数名修饰规则而的字符串再找地址,是时候兑现承诺了)                           =》生成一个.exe可执行文件(Linux下为.out文件)

       当链接是未找到报链接错误(只用声明无定义),非编译错误(语法错误)。

?fub@@YAXXZ

这就是VS下fub函数由函数名修饰规则的产物。objdump -S   .aut文件

2.4.7.2 函数名修饰的规则和寻址的使用  

2.4.7.2.1  函数名修饰的规则

C++   看函数名+参数列表  (名参不同,修饰的名不同,地址不同)

        Linux    _Z+函数名字符个数+函数名+参数列表中各参数首字母

int test(int a = 2,int b = 3);   Linux下修饰的函数名为_Z4testii

   在centos7.6的环境下    

VS        

C        看函数名

Linux   只看函数名

int  add ( int a,int b );

vs   

2.4.7.2.2  修饰的函数名寻址时的使用

 1生成符号表

        在含有函数定义的.s文件汇编生成二进制的.o文件时,会生成一个修饰好的函数名与函数地址一一对应的符号表。

 2查表的地址

        在各.o文件进行合并时,会依据占位的函数修饰名通过符号表进行函数地址的补全。

  • 24
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值