C++初阶 —— 函数重载

简介: C++初阶 —— 函数重载

【写在前面】

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是 “谁也赢不了!”,后者是 “谁也赢不了!”

一、 函数重载概念

函数重载:是函数的一种特殊情况,C++ 允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表 (参数个数或类型或顺序) 必须不同,常用来处理实现功能类似数据类型不同的问题,显然这是 C 语言做不到的东西

//1.参数个数
int Add(int x)
{}
int Add(int x, int y)
{}
//2.参数类型
int Add(int x, int y)
{}
int Add(int x, double y)
{}
//3.参数顺序
int Add(int x, float y)
{}
int Add(float y, int x)
{}

❗ 怎么调用 ❕

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;
}

⚠ 注意

对于函数重载,如果你想调用某一函数,那么在传参的时候就必须写好对应参数的类型、个数、顺序,比如 float 数据,就要写 3f,因为这样它才能找到对应的函数调用

二、 名字修饰 (name Mangling)

❓ 为什么C++支持函数重载,而C语言不支持函数重载呢,以 Linux 环境下演示 ❔

注意这里就不细讲 Linux 的一些指令了,具体的我都写在或者将写在 《Linux专栏》里了

先在 Linux 下以两种编译方式编译函数重载的程序,这里有三个文件 :f.h、f.c、test.c

  ▶ 可以看到以 C 语言去编译函数重载报错了

  ▶ 可以看到以 C++ 去编译函数重载是可以的

在正式探究前我们先回忆下,注意 C/C++ 都有类似的过程,但肯定是有区别的,现在我们要找的就是那个区别

  这里我们对照着程序走一遍过程

然后再回到我们的问题

  ❓ C语言不支持函数重载 ❔

   C 编译器,直接用函数名关联,函数名相同时,无法区分

  ❗ 验证 ❕

   通过命令 objdump -S 去查看 C 编译生成的符号表

   通过命令 objdump -S 去查看 C++ 编译生成的符号表

  ❓ C++ 支持函数重载 ❔

   从上就可以看出对于函数重载 C++ 相对于 C 语言引入了某种规则

   C++ 引用了《函数名修饰规则 (Linux下)》不能直接用函数名,要对函数名进行修饰 (带入参数的特点修饰)

    📝 说明:

     1️⃣ _Z 是前缀

     2️⃣ 3 是函数名的长度

     3️⃣ Add 是函数名

     4️⃣ ii / dd 是函数参数类型的首字母,如果是 int* i,那么就是 pi

💨小结:

  C++ 是支持函数重载的,函数名相同,只要参数不同,修饰在符号表中的名字也不同,那么就能区分了

❗ Windows下函数名修饰规则 ❕

🍳【扩展学习:C/C++函数调用约定和名字修饰规则】

C++函数重载

C/C++ 函数调用约定

❓ 下面两个函数属于函数重载吗 (编译器能不能只实现返回值不同,就能构成重载) ❔

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

显然《函数名修饰规则》并不能让它们支持重载。

 ❓ 其次如果想自己定义《函数名修饰规则》让只有返回值不同的函数支持重载可以吗 ❔

  💨 编译器层面是可以区分的

   short Add; -> _Z3sAdd

   int Add; -> _Z3iAdd

  💨 语法调用层面有严重歧义

   Add(3, 5); ???

❓ 下面两个函数能形成函数重载吗?❔

void TestFunc(int a = 10)
{
  cout<<"void TestFunc(int)"<<endl;
}
void TestFunc(int a)
{
  cout<<"void TestFunc(int)"<<endl;
}

虽然两个函数的参数是缺省值和非缺省值,但是依旧不影响修饰出来的函数名,所以不能构成函数重载

三、 extern"C"

有时候在 C++ 工程中可能需要将某些 (部分) 函数按照 C 的风格来编译,在函数前加 extern “C”,意思是告诉编译器,将该函数按照 C 语言规则来编译。比如:tcmalloc 是 google 用 C++ 实现的一个项目,他提供 tcmallc() 和 tcfree两个接口来使用,但如果是 C 项目就没办法使用,那么他就使用 extern “C” 来解决。

extern "C" int Add(int left, int right);
int main()
{
  Add(1,2);
  return 0; 
}

💨总结

  1️⃣ C++ 项目可以调用 C++ 库,也可以调用 C 的库,C++ 是直接兼容 C 的

  2️⃣ C 项目可以调用 C 库,也可以使用 extern"C" 调用 C++ 库 (C++ 提供的函数加上 extern"C")


相关文章
|
14天前
|
程序员 C++
C++中的函数重载有什么作用
【10月更文挑战第19天】C++中的函数重载有什么作用
13 3
|
14天前
|
编译器 程序员 C++
C++中的函数重载是什么
【10月更文挑战第19天】C++中的函数重载是什么
12 0
|
1月前
|
自然语言处理 编译器 Linux
【C++】巧用缺省参数与函数重载:提升编程效率的秘密武器
【C++】巧用缺省参数与函数重载:提升编程效率的秘密武器
|
1月前
|
程序员 C++ 开发者
C++入门教程:掌握函数重载、引用与内联函数的概念
通过上述介绍和实例,我们可以看到,函数重载提供了多态性;引用提高了函数调用的效率和便捷性;内联函数则在保证代码清晰的同时,提高了程序的运行效率。掌握这些概念,对于初学者来说是非常重要的,它们是提升C++编程技能的基石。
21 0
|
3月前
|
编译器 程序员 C语言
C++函数重载
在实际开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,这两个变量有多种类型,可以是 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 变量的
C++函数重载
|
3月前
|
编译器 Linux C语言
【C++小知识】为什么C语言不支持函数重载,而C++支持
【C++小知识】为什么C语言不支持函数重载,而C++支持
|
3月前
|
安全 编译器 C++
C++入门 | 函数重载、引用、内联函数
C++入门 | 函数重载、引用、内联函数
31 5
|
4月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
5月前
|
存储 编译器 C++
【C++ 初阶路】--- 类和对象(下)
【C++ 初阶路】--- 类和对象(下)
23 1
|
5月前
|
存储 编译器 C语言
【C++初阶路】--- 类和对象(中)
【C++初阶路】--- 类和对象(中)
27 1