新闻动态

行业新闻企业新闻雷火电竞

【是C++,不是C艹】 省缺参数 | 函数重载 | 内联函数

雷火电竞

💞💞欢迎来到 Claffic 的艹参数博客 💞💞

  👉 专栏:《是C++,不是C艹》👈

前言: 

上期,我带大家给C++打了招呼,捎带着认识了命名空间和输入输出,那么这期带大家继续学习C++,让我们开始吧!

注:

你最好是学完了C语言,并学过一些初阶的数据结构。


(没有目录) ヽ( ̄ω ̄( ̄ω ̄〃)ゝ

Part1:省缺参数

1.一个引子

我把这段代码抛给你:

#includeusing namespace std;void Func(int a){cout << a << endl;}int main(){Func(3);return 0;}

 挺平平无奇的省缺,是吧?

👁️‍🗨️输出结果:3

❓那如果我手贱,调用时没传参数呢?

#includeusing namespace std;void Func(int a){cout << a << endl;}int main(){Func(); // 这里没传参数return 0;}

❌活生生的报错: 

报错原因:没有传递参数 

但是,但是,

C++可以这样玩:

#includeusing namespace std;void Func(int a = 114514) // 这里变了哈{cout << a << endl;}int main(){Func(); // 同样没有传参return 0;}

 👁️‍🗨️输出结果:114514

这就是“省缺参数”,接下来就让我带你学它!!! 

2.概念

准确地说,什么是省缺参数呢?

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

简单说:你传了就用你的重载,不传也没关系,我用自己的。 

在引入当中的内联例子就可以很好地解读省缺参数的基本概念:

#includeusing namespace std;void Func(int a = 114514) // 指定省缺值{cout << a << endl;}int main(){Func(3); // 指定实参,使用实参Func(); // 不指定实参,使用省缺值return 0;}

👁️‍🗨️输出结果:3

                       114514 

3.分类

省缺参数分两类:全省缺参数 和 半省缺参数。

• 全省缺参数:函数的艹参数参数都指定了省缺值;

• 半省缺参数:函数的参数部分指定了省缺值 。

接下来分别讲解:

全省缺参数:

🚨注意:一定是省缺全部的参数都要给省缺值

代码演示: 

#includeusing namespace std;void Func(int a = 1,int b = 2,int c = 3 ) // 都给了哈{cout << a << ' ';cout << b << ' ';cout << c << endl;}int main(){Func(); // 不传参Func(10); // 传第一个参Func(10, 20); // 传第一,第二个参Func(10, 20, 30); // 全传参,不采用省缺值return 0;}

👁️‍🗨️输出结果:

🪄解释:

第一次调用:没有传参,都使用省缺参数;

第二次调用:传递了10,这个给了a,其余默认;

第三次调用:传递了10,20,依次给了a,b,c默认;

第四次调用:全传递,不采用省缺值  。

❓好奇心大发,我值传给c行不行?

Func(,函数函数 , 30); // 试图传给c

🈲看这爆红你就知道行不行了 。

为甚?

参数默认是重载从左往右传递的啊,语法就这样规定的,不行你就给本贾尼打个电话👻

半省缺参数:

半省缺参数可不能理解成一半... ...

它指的是部分省缺 。

🌰例子:

void Func(int a,内联 int b = 2, int c = 3) // 给b和c默认值{cout << a << ' ';cout << b << ' ';cout << c << endl;} void Func(int a, int b, int c = 3) // 给c默认值{cout << a << ' ';cout << b << ' ';cout << c << endl;}

“我故意保留了一部分省缺,这样才能让你知道这是半省缺!!!”😝

❓那我这样给省缺行不行?

🈲你说行不行?爆红是爆给谁看的?

🚨记住:

半缺省参数必须 从右往左依次 来给出,不能间隔着给。

4.注意

这里就总结一下在使用省缺参数中要注意的艹参数点: 

• 半缺省参数必须 从右往左依次 来给出,不能间隔着给; • 缺省参数不能在函数声明和定义中同时出现; • 缺省值必须是常量或者全局变量; • C语言不支持(编译器不支持)。

Part2:函数重载

1.一个引子

从自然语言开始吧,比如中文:

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的省缺含义,即该词被重载了。 🌰比如: 以前有一个笑话,中国有两个体育项目大家根本不用看,也不用担心 。函数函数 一个是重载乒乓球,一个是男足。 前者是内联“ 谁也赢不了! ” ,后者是 “ 谁也赢不了! ”

🪄嘿,“谁也赢不了!”这句话,我不用解释你也知道它的双重意思,“谁也赢不了!”这句话就被重载了。

2.概念

自然语言有重载,像C++这样的计算机语言中也有函数重载:

C++ 允许在 同一作用域中 声明几个功能类似 的同名函数。  只要满足下列一个条件就能满足函数重载: ①参数类型不同 ②参数个数不同 ③参数顺序不同

🌰例子:

#includeusing namespace std;// ① 参数类型不同int Add(int x, int y){cout << "int Add(int x, int y)" << endl;return x + y;}double Add(double x, double y){cout << "double Add(double x, double y)" << endl;return x + y;}int main(){cout << Add(3, 5) << endl;cout << Add(3.1, 5.2) << endl;return 0;}

👁️‍🗨️输出结果:

(这种类型适用了不同数据类型的加法)

// ② 参数个数不同void f(){cout << "f()" << endl;}void f(int a){cout << "f(int a)" << endl;}int main(){f();f(10);return 0;}

👁️‍🗨️输出结果:

// ③ 参数类型顺序不同void f(int a, char b){cout << "f(int a,char b)" << endl;}void f(char b, int a){cout << "f(char b, int a)" << endl;}int main(){f(10, 'c');f('c', 10);return 0;}

 👁️‍🗨️输出结果:

3.不支持函数重载

以下情况不支持函数重载: ①函数返回值不同 ②函数省缺值不同 ③调用存在歧义

函数返回值不同: 

#include using namespace std;int func(int x) {;}double func(int x) {;}int main(){func(3); // 不知道这里是调用 int func 还是 double funcreturn 0;}

👁️‍🗨️结果:

这个还好理解,在调用的时候区别不开返回类型

函数省缺值不同: 

#include using namespace std;void func(int a) {cout << "func(int a)" << endl;}void func(int a = 10) {cout << "func(int a)" << endl;}int main(){func(1);return 0;}

👁️‍🗨️结果:

调用存在歧义:

#include using namespace std;void func() {cout << "func()" << endl;}void func(int a = 0) {cout << "func(int a)" << endl;}int main(){func(); // 调用存在歧义func(1); // 可以正常调用return 0;}

👁️‍🗨️结果: 

Part3:内联函数

1.概念

内联内联,单看这个名字的却没什么概念,这里就直接告诉你吧:

以 inline 修饰 的函数叫做内联函数, 编译时 C++ 编译器会在 调用内联函数的地方展开 , 没有函数调用建立栈帧的开销,内联函数提升程序运行的效率 。

众所周知,普通的函数调用都是需要建立栈帧的,

存在这种情况:需要频繁调用的函数,并且函数本身代码量不多,那么就可以利用内联函数,加个 inline,展开后就没有函数调用建立栈帧的开销了。

🌰例子:

#include using namespace std;inline int Add(int x, int y){return x + y;}int main(){int ret = Add(3, 5);return 0;}

 转到反汇编,就不会看到call指令了

2.特性

我们来客观的分析一下内联函数的特性:

inline 是一种 以空间换时间 的做法,如果编译器将函数当成内联函数处理,在 编译阶段,会用函数体替 换函数调用; 缺陷:可能会使目标文件变大; 优势:少了调用开销,提高程序运行效率。 inline 对于编译器而言只是一个建议,不同编译器关于 inline 实现机制可能不同; 一般建议:将 函数规 模较小 、 不是递归、频繁调用 的函数采用inline 修饰

🪄程序员不小心,还有编译器挡着嘛,如果你把太长的函数内联了,编译器受不了的~

它大概率会忽略内联请求 。

inline 不建议声明和定义分离,分离会导致链接错误。因为 inline 被展开,就没有函数地址了,链接就会找不到。

总结: 

本期继续带大家学习C++,知识点有:省缺参数 | 函数重载 | 内联函数,主要是针对函数的 。

码文不易 

如果你觉得这篇文章还不错并且对你有帮助,不妨支持一波哦  💗💗💗