C++初阶 —— 函数重载

Posted 跳动的bit

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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")

以上是关于C++初阶 —— 函数重载的主要内容,如果未能解决你的问题,请参考以下文章

C++初阶:入门总结命名空间 | 缺省参数 | 函数重载 | 引用 | 内联函数

C++初阶:类和对象(中篇)构造函数 | 析构函数 | 拷贝构造函数 | 赋值运算符重载

C++ 初阶 新语言入门介绍:命名空间,(全/半)缺省函数,函数重载,引用,内联,auto

C++ 初阶 新语言入门介绍:命名空间,(全/半)缺省函数,函数重载,引用,内联,auto

C++初阶 关键字,命名空间,缺省参数,IO和函数重载

C++初阶 —— 类和对象(中篇)