博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++函数重载及其实现原理
阅读量:4185 次
发布时间:2019-05-26

本文共 2140 字,大约阅读时间需要 7 分钟。

在实际开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,这两个变量有多种类型,可以是 int、float、char、bool 等,我们需要通过参数把变量的地址传入函数内部。在C语言中,程序员往往需要分别设计出三个不同名的函数,其函数原型与下面类似:

void swap1(int *a, int *b); //交换 int 变量的值void swap2(float *a, float *b); //交换 float 变量的值void swap3(char *a, char *b); //交换 char 变量的值void swap4(bool *a, bool *b); //交换 bool 变量的值

但在C++中,这完全没有必要。C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading)

函数重载是函数的一种特殊情况,c++允许在同一作用域中声明几个功能类似的函数,这些函数的形参列表必须不同,常用来实现功能类似类型不同的问题。

int Add(int left,int right){Return left+right;} Double Add(int left,int right){Return left+right;} Char Add(int left,int right){Return left+right;}/*********************************************/ int main(){Add(1,2);//整型Add(1.0,2.0);//浮点型--默认是double类型 若变成float型 -->Add(1.0f,2.0f);Add(‘1’,‘2’);//字符型}结果:-->编译时会进行参数类型推演,检测参数类型选择相匹配的函数类型33.0C  //说明:(字符1的ASC码是49;字符2的ASC码是50--->打印ASCC码为99的字符)

函数重载条件

1:必须在同一个作用域。

2:函数名字必须相同

3:形参列表必须不同

参数个数不一样

参数类型不一样
参数类型次序不同

例:void Funtest(){}void Funtest(int a){} //①void Funtest(int a){}void Funtest(char a){}//②void Funtest(int a,char a){}void Funtest(char a,int a){}//③

此外:

仅仅返回值不同是不能构成函数重载的—原因:调用不明显

例:void Funtest(){} Int Funtest(){Return 0;}

报错-有歧义问题—编译器不知道调用以上哪一个函数

void Funtest(){}void Funtest(int a=10){}  Int main(){Funtest(); Return 0;}

那么为什么c++支持函数重载而C语言不支持函数重载呢?这就与C和C++中,编译器对函数名字的修改规则相关。

C与C++中,编译器对函数名字的修改规则:(c++函数重载底层处理)

我们以vs编译器下为例作出验证:

在c++底层有重命名机制。

例:int Add(int left,int right);

编译之后函数名修改为(?Add@@YAHHH@Z)

Char Add(int left,int right);

编译之后函数名修改为(?Add@@YADHH@Z)

那么我们从上面可以知道,在c++中,底层的重命名机制将Add函数根据参数的个数,参数的类型,返回值的类型都做了重新命名。给定了返回值类型和参数类型,所以在编译之后,不会有重定义情况出现。

C语言中,编译之后C语言链接器将函数名改为_Add ,没有给定返回值类型和参数类型,所以会重定义

那么,c++能否将一个函数按照c的风格来编译呢?

答案肯定是可以的。

我们在C++ 程序中调用被 C 编译器编译后的函数时,添加extern “C”

Extern “C” int Add (int left ,int right)

原因:

①C++语言支持函数重载。而C不支持函数重载。

②函数在C中和C++中编译过的函数名字是不一样的。加上extern”C”是说明是说明C已经编译过的。

C++想要调用已经编译过的C函数,由于编译过的名字不同,是不能直接调用的,所以C++加extern“C”生命来解决这个问题。

例如:假设某个函数的原型为: void foo(int x, int y);该函数被C 编译器编译后在库中的名字为_foo, 而C++ 编译器则会产生像_foo_int_int 之类的名字,加上extren”C”后,就相当于告诉编译器,函数foo是个C编译后的函数,在库里应该找的是_foo,而不是_foo_int_int.

思考:

仅是否带缺省参数区别的函数,会构成重载吗?

例如:void Funtest(int a = 10){    cout<<"void Funtest(int)"<

转载地址:http://avuoi.baihongyu.com/

你可能感兴趣的文章
Java实现简单的RPC框架
查看>>
为什么Netty这么火?与Mina相比有什么优势?
查看>>
TCP的ACK原理和延迟确认机制
查看>>
TCP超时与重传机制
查看>>
Reactor和Proactor对比以及优缺点(netty的底层原理reactor模型)
查看>>
Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
查看>>
IO模型及select、poll、epoll和kqueue的区别
查看>>
Nginx+Keepalived高可用集群
查看>>
IP协议详解
查看>>
kafka:sync、async以及oneway 几种发送消息模式
查看>>
Kafka中关于 消息的“顺序消费”讨论
查看>>
Rocketmq原理&最佳实践
查看>>
kafka 分区 leader 选举机制原理
查看>>
使用import scope解决maven继承(单)问题
查看>>
Java注解
查看>>
Mysql 表备份 & update的字段来自另一张表
查看>>
深入理解Java类加载器(ClassLoader)
查看>>
虚拟机类加载机制和new对象的过程
查看>>
自定义类加载器与spring的集成
查看>>
理解Java ClassLoader机制
查看>>