C++中的函数重载分析(一)
1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复;
2,自然语言中的上下文:
1,你知道上面词汇中“洗”字的含义吗?
1,不同的动词和名次搭配的含义是不同的;
2,结论:
1,能和“洗”字搭配的词汇有很多;
2,“洗”字和不同的词汇搭配有不同的含义;
3,重载(Overload)的概念:
1,重载是同一个标识符在不同的上下文有不同的意义;
2,如:
1,“洗”和不同的词汇搭配后有不同的含义;
1,洗衣服,洗脸,洗脑,洗马桶,...;
2,“play”和不同的单词搭配后有不同的含义;
1,play chess, play piano, play basketball, ...;
4,思考:
1,重载在自然语言中是随处可见的,那么程序设计中是否也有重载呢?
1,让程序设计语言接近自然语言,所以计算机科学家在设计语言的时候就考虑将人类的语言习惯引进到程序设计语言中,C++ 就引入了重载的概念;
2,程序设计语言中和动词接近的是函数,所以 C++ 中选择函数来实现重载的概念;
5,C++ 中的函数重载:
1,函数重载(Function Overload):
1,用同一个函数名定义不同的函数;
1,这是 C++ 中重载的概念;
2,C++ 后续语言也是这样实现重载;
2,当函数名和不同的参数搭配时函数的含义不同;
1,当函数名和不同的参数搭配时实现了函数重载;
1,函数名类似动词,参数类似名词;
2,含义的不同在于所执行的函数体不同;
3,代码示例:
int func(int x)
{
return x;
} int func(int a, int b)
{
return a + b;
} int func(const char* s)
{
return strlen(s);
}
2,函数重载初探编程实验:
1,main.cpp 文件:
#include <stdio.h>
#include <string.h> int func(int x)
{
return x;
} int func(int a, int b)
{
return a + b;
} int func(const char* s)
{
return strlen(s);
} int main(int argc, char *argv[])
{
printf("%d\n", func());
printf("%d\n", func(, ));
printf("%d\n", func("D.T.Software")); return ;
}
2,输出结果:
3
9
12.
3,C++ 支持函数重载,它是根据自然语言中的重载概念得来的;
6,函数重载至少满足下面一个条件(数类序):
1,参数个数不同;
2,参数类型不同;
3,参数顺序不同;
7,当函数默认参数遇上函数重载会发生什么?
1,代码示例:
int func(int a, int b, int c = )
{
return a * b * c;
} int func(int a, int b) // 个数不同,构成重载;
{
return a + b;
} int main()
{
int c = func(, ); // which one? return ;
}
8,函数默认参数 VS 函数重载编程实验:
1,main.cpp 文件:
#include <stdio.h> int func(int a, int b, int c = )
{
return a * b * c;
} int func(int a, int b)
{
return a + b;
} int main(int argc, char *argv[])
{
int c = func(, ); // error: call of overloaded 'func(int, int)' is ambiguous return ;
}
2,这里是 C++ 中第一个特性冲突,后续 Java、C# 语言上述的默认参数值是不允许的,因为程序设计时,不允许二义性;
9,编译器调用重载函数的准则:
1,将所有同名函数作为候选者;
2,尝试寻找可行的候选函数;
1,精确匹配实参;
2,通过默认参数能够匹配实参;
3,通过默认类型转换匹配实参;
3,匹配失败:
1,最终寻找到的候选函数不唯一,则出现二义性,编译失败;
2,无法匹配所有候选者,函数未定义,编译失败;
10,函数重载的注意事项:
1,重载函数在本质上是相互独立的不同函数;
2,重载函数的函数类型不同;
3,函数返回值不能作为重载的依据;
1,函数重载是由函数名和参数列表决定的;
11,函数重载的本质编程实验:
1,main.cpp 文件:
#include <stdio.h> int add(int a, int b) // 函数类型为 int(int, int);
{
return a + b;
} int add(int a, int b, int c) // 函数类型为 int(int, int, int);
{
return a + b + c;
} int main()
{
printf("%p\n", (int(*)(int, int))add);//函数名 add 是函数入口地址,当只用add来得到地址时,由于重载的原因,编译器在此处显示 error: overloaded function with no contextual information,而当不是重载的函数时,可以直接使用 add 来获取函数地址;这里通过强制类型转换将 add 转换为 (int(*)(int, int)) 这样的函数指针;
printf("%p\n", (int(*)(int, int, int))add); return ;
}
2,输出结果:
00DF100A
00DF100F
3,结论 1:
1,函数的入口地址不同,可以反向的证明这是两个不同的函数;
4,通过 VS 命令行运行命令“dumpbin /symbols ProgramName.obj路径”查看 VS 中的工程符号表中的如下两行:
00E 00000000 SECT3 notype () External | ?add@@YAHHH@Z (int __cdecl add(int,int))
1,C++ 编译器编译 int __cdecl add(int,int) 函数后,在符号表中认为标识符为 ?add@@YAHHH@Z;
01F 00000000 SECT7 notype () External | ?add@@YAHHHH@Z (int __cdecl add(int,int,int))
1,C++ 编译器编译 int __cdecl add(int,int,int) 函数后,在符号表中认为标识符为 ?add@@YAHHHH@Z;
5,结论 2:
1,编译器在编译这两个函数的时候,已经分开对待了,编译器获得的这两个函数的名字是不同的;
2,编译器认为这是两个不同的函数,所以编译出的最终结果也就是可执行程序中这两个函数的入口地址是不同的;
6,总的结论:
1,不管正向推还是反向推,C++ 语言中重载函数的本质其实是不同的函数;
12,小结:
1,函数重载是 C++ 中引入的概念;
2,函数重载用于模拟自然语言中的词汇搭配;
3,函数重载使得 C++ 具有更丰富的语义表达能力;
1,让 C++ 编程更符合人类思维习惯;
4,函数重载的本质为相互独立的不同函数;
5,C++ 中通过函数名和函数参数确定函数调用;
1,返回值不参与重载过程;
C++中的函数重载分析(一)的更多相关文章
- C++中的函数重载分析(二)
1,重载与指针: 1,下面的函数指针将保存哪个函数的地址? int func(int x) { return x; } int func(int a, int b) { return a + b; } ...
- Oracle 中 decode 函数用法
Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译 ...
- mysql中now()函数的使用,还有oracle的sysdate,可能埋下的坑
mysql中now()函数的使用,还有oracle的sysdate 在需求中如果系统中药添加当前操作的时间那么很简单的一个操作在写sql的时候直接在这个字段对应的位置写上now()函数就可以了,这样就 ...
- 程序代码中退出函数exit()与返回函数return ()的区别
程序代码中退出函数exit()与返回函数return ()的区别 exit(0):正常运行程序并退出程序: exit(1):非正常运行导致退出程序: return():返回函数,若在主函数 ...
- mysql中find_in_set()函数的使用
首先举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点.4图文等等 .现在有篇文章他既是头条,又是热点,还是图文,type中以 1,3,4 的格式存储.那我 ...
- QT中使用函数指针
想仿命令行,所以定义了一个类,让一个String 对应一个 function,将两者输入list容器. 类中定义了 QString commandStr; void (MainWindow::*com ...
- Bash 是如何从环境变量中导入函数的
在上文中曾说到: 所谓的环境变量的真实面目其实就是个任意字符串 Bash 在启动时会将 environ 数组中包含 = 号的字符串导入成为自己的变量 Bash 在启动外部命令时会将自己内部标记为环境变 ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- PHP中spl_autoload_register()函数的用法
spl_autoload_register (PHP 5 >= 5.1.2) spl_autoload_register — 注册__autoload()函数 说明 bool spl_autol ...
随机推荐
- python接口自动化四(json数据处理)
前言 有些post的请求参数是json格式的,这个前面第二篇post请求里面提到过,需要导入json模块处理. 一般常见的接口返回数据也是json格式的,我们在做判断时候,往往只需要提取其中几个关键的 ...
- [LOJ 6704] 健身计划
问题描述 九条可怜是一个肥胖的女孩. 她最近长胖了,她想要通过健身达到减肥的目的,于是她决定每天做n次仰卧起坐以达到健身的目的. 她可以将这n次动作分为若干组完成,每一次完成ai次仰卧起坐,每做完一次 ...
- 转 弹性反向传播(RProp)和均方根反向传播(RMSProp)
from http://blog.csdn.net/tsq292978891/article/details/78619384 都是一种权值更新算法,类似于SGD算法,其中,RMSProp是RProp ...
- org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression:
org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression:
- Python语言中enumerate()及zip()函数的使用例子
在Python编程语言中,enumerate()及zip()是两个常用的内置函数,这两个函数功能类似,但又有所区别,下面通过两个例子分别进行说明. enumerate()函数 该函数在字面上是枚举.列 ...
- javascript注
1.浮点数: e表示法(科学计数法-10的指数次幂): let floatNum = 3.12e2; //等于312 浮点数的最高精度是17位小数. 浮点数计算精度远不如整数,0.15加0.15的和是 ...
- Linux NTP服务器的搭建及client自动更新时间
Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间 ...
- 洛谷P1198 [JSOI2008]最大数(单点修改,区间查询)
洛谷P1198 [JSOI2008]最大数 简单的线段树单点问题. 问题:读入A和Q时,按照读入一个字符会MLE,换成读入字符串就可以了. #include<bits/stdc++.h> ...
- memcached空指针内存错误与死循环问题分析(memcached dead loop and crash bug! issue #260 and issue #370)
(由于这是发在memcached邮件列表的,所以只能用一下蹩脚的英文了) (you should read the discuss about issue #260 first: https://g ...
- easyhook源码分析一
easyhook简要说明: easyhook是一个开源的hook库(http://easyhook.github.io/),其支持托管代码(.NET)和非托管代码(C/C++)hook,这里只分析了其 ...