函数重载

一、概念

C++ 允许在同一作用域中存在几个功能类似的同名函数,但这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同

int Add(int left, int right)
{
  return left+right;
}
 
double Add(double left, double right)
{
  return left+right;
}

long Add(long left, long right)
{
  return left+right;
}
 
int main()
{
  Add(10, 20);
  Add(10.0, 20.0);
  Add(10L, 20L);
  return 0;
}

二、名字修饰(Name Mangling) - 导致 C 和 C++ 代码不能直接相互调用

C/C++ 代码要运行起来,需要经历预处理、编译、汇编、链接这四个阶段,而 Name Mangling 是一种在编译期间将函数名重新修饰的机制,简单来说,就是编译器为了区分各个函数,通过 Name Mangling 保证在底层的全局唯一性

C 的名字修饰规则非常简单,只是在函数名前添加了下划线,这也是 C 不支持函数重载的原因

/*
 * test.c
 */
int Add(int left, int right);
 
int main()
{
  Add(1, 2);  // 编译器链接报错:error LNK2019: 无法解析的外部符号 _Add,该符号在函数 _main 中被引用
  return 0;
}

由于 C++ 要支持函数重载、命名空间、类等,使得其名字修饰规则比较复杂,不同编译器在底层的实现方式可能会有差异

int Add(int left, int right);
double Add(double left, double right);
 
int main()
{
  Add(1, 2);      // 编译器链接报错:error LNK2019: 无法解析的外部符号 "int __cdecl Add(int,int)" (?Add@@YAHHH@Z)
  Add(1.0, 2.0);  // 编译器链接报错:error LNK2019: 无法解析的外部符号 "double cdecl Add(double,double)" (?Add@@YANNN@Z)
  return 0;
}
函数签名修饰后名称
int func(int)?func@@YAHH@Z
float func(float)?func@@YAMM@Z
int C::func(int)?func@C@@AAEHH@Z
int C::C2::func(int)?func@C2@C@@AAEHH@Z
int N::func(int)?func@N@@YAHH@Z
int N::C::func(int)?func@C@N@@AAEHH@Z

三、extern “C” - 解决 C 和 C++ 代码间相互调用问题

有时候,C++ 工程中需要将某些函数按照 C 规则进行编译,在函数前加 extern “C”,意思是告诉编译器,将该函数按照 C 规则进行编译

extern "C" int Add(int left, int right);
 
int main()
{
  Add(1,2);  // 链接时报错:error LNK2019: 无法解析的外部符号_Add,该符号在函数 _main 中被引用
  return 0;
}

C、C++ 混合调用

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值