自学内容网 自学内容网

【C++初阶(二)】缺省参数以及函数重载

1. 前言

写C语言代码的时候
特别是在写数据结构时:

经常忘记传函数的参数
或者当前不需要什么参数

C++增加了缺省参数来解决这个问题

而为了解决相似功能的函数的函数名问题

C++增加了函数重载来解决这个问题

本篇文章将简单介绍缺省参数
并着重讲解函数重载的底层原理!


2. 缺省参数

缺省参数是声明或定义函数时
为函数的参数指定一个缺省值
在调用该函数时,
若没有指定实参
则采用该形参的缺省值
否则使用指定的实参

缺省参数分类:

  1. 全缺省
  2. 半缺省

2.1 全缺省

类似于这样的代码:

void Func(int a = 10, int b = 20, int c = 30)
 {
     cout<<"a = "<<a<<endl;
     cout<<"b = "<<b<<endl;
     cout<<"c = "<<c<<endl;
 }

全缺省指的是函数的所有参数都给缺省值

有四种调用此函数的方式:

  1. 什么都不传:
Func();

此时系统默认a,b,c的值分别为
10 - 20 - 30

  1. 只传一个参数:
Func(15);

此时,a的值为15
而系统默认b,c的值为
:20-30

  1. 传两个参数:
Func(15,25);

此时a,b的值为:15 - 25
系统默认c的值为30

  1. 三个参数都传:
Func(15,25,35);

此时a,b,c的值为:15-25-35


注意: 传参不能写成这种形式:

Func(,25,);
Func(,,35);
Func(,25,35);
Func(15,,35);

2.2 半缺省

半缺省类似于这种形式:

void Func(int a, int b = 10, int c = 20)
 {
     cout<<"a = "<<a<<endl;
     cout<<"b = "<<b<<endl;
     cout<<"c = "<<c<<endl;
 }

只要有参数没有给缺省值
那么它就是半缺省的

注意:

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现
  3. 缺省值必须是常量或者全局变量

比如下面这样定义半缺省是不行的:

void Func1(int a=10,int b,int c);
void Func2(int a,int b=20,int c);
//有缺省值的前提是它的右边的参数都有缺省值

3. 函数重载概念

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

举个例子:

void func(int i,char ch) //函数1
{
//...
}

void func(char ch,int i) //函数2
{
//...
}

函数1和2可以同时存在
并且它们不是同一个函数


4. 几种不同类型的函数重载

总结三种支持函数重载的情况:

  1. 参数类型不同
int Add(int left, int right)
{
return left + right;
}
double Add(double left, double right)
{
return left + right;
}
  1. 参数个数不同
void f()
{
 cout << "f()" << endl;
}
void f(int a)
{
 cout << "f(int a)" << endl;
}
  1. 参数类型顺序不同
void f(int a, char b)
{
 cout << "杭州电子科技大学" << endl;
}
void f(char b, int a)
{
 cout << "圣光机联合学院" << endl;
}

(注意:下面这种不属于函数重载):

short Add(short x,short y)
{
return x+y;
}
int Add(short x,short y)
{
return x+y;
}

因为它们参数类型,数量,顺序都一样
只是返回值不同,不构成函数重载!


5. C++如何支持函数重载?

在C/C++中,一个程序要运行起来
需要经历以下几个阶段:

  • 预处理
  • 编译
  • 汇编
  • 链接

因为c++区别于c在这几个过程中
的差别,所以使C++能够支持函数重载


5.1 C程序为什么不支持函数重载?

定义两个源文件和一个头文件来解释:

  • func.h
  • func.c
  • main.c

在.h文件声明两个函数

int func(int x,int y);
int func(int x,double y);

这三个文件会经历以下过程:

  1. 预处理阶段

主要内容:头文件展开,宏替换
条件编译,去掉注释

这个过程结束后,func.h被展开了
main.c和func.c源文件变成了:
func.i和main.i文件

  1. 编译阶段

主要内容:语法检查和生成汇编代码

这个过程结束后,func.i和main.i
文件变成了func.s和main.s文件
(此文件中为汇编代码)

  1. 汇编阶段

主要内容:将汇编代码转换成二进制码
以便机器能够读懂

这个过程结束后,func.s和main.s
文件变成了func.o和main.o文件

注:前面的过程只用了解,真正的主角在下面!

  1. 链接过程
    func.o和main.o文件
    以及链接过程是这部分的重中之重

5.2 C程序的链接过程

func.c到func.o和main.c到main.o
都是单线程的

链接过程:

.o的目标文件会合并到一起
其次还需找一些只给了声明的函数
的函数地址

而每一个.o文件都有一个符号表
符号表中存放函数的地址

当main文件要调用这个函数时
会去符号表中找函数的地址

在这里插入图片描述

而符号表中两个func函数的地址
编译器不知道应该调用哪个
所以c程序不支持函数重载!


5.3 C++函数名修饰规则

相比起C程序而言,C++新增了一个
函数名修饰规则来支持函数重载

这个规则就是将函数的参数带入符号表
所以参数的类型,数量,顺序不同
代表的是不同的函数,找地址时就不会出错!

我们在C++的汇编代码中找到了
这两个函数对应的部分:

在这里插入图片描述

综上所述:

函数参数的类型,数量,顺序不同
那么对应在符号表中的名字就不一样
main文件再去找函数地址时就不会冲突

对比c程序:
c程序符号表中只有一个函数名
函数参数没有参与进来
所以C程序不支持相同函数名的函数


6. 总结以及拓展

前面很多过程只是为了
后面的链接.o文件打基础
所以前面的听不懂也没关系

只需要知道C++有函数名修饰规则
c++的.o文件的符号表的函数名
和函数参数相关
而c程序的符号表和参数无关!

拓展:
C/C++函数调用约定和名字修饰规则
有兴趣好奇的同学可以看看里面
有对vs下函数名修饰规则讲解
C/C++约定


🔎 下期预告:引用和内联函数 🔍

原文地址:https://blog.csdn.net/iwanna1fd/article/details/145263662

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!