在完成了第三章的学习后,为了便于日后的复习整理,我制作了一张思维导图,有需要的可以自取。

函数的定义与使用

带默认值的函数

在C++中我们可以为函数添加默认的参数值,在调用时可不传入或部分传入参数,为传入的部分便会采用默认值。

带默认参数的函数可以放在main函数前。

#include <iostream>using namespace std;int add(int a = 5, int b = 6){ return a + b;}int main(void){ cout<<add(); return 0;}

也可把函数放在main函数后,将默认值放在函数声明中。

这种情况下,默认值只可出现在函数声明中,不可出现在函数定义中

#include <iostream>using namespace std;int add(int a = 5, int b = 6);int main(void){ cout << add(); return 0;}int add(int a, int b) //add(int a = 5,b = 6)为错误写法{ return a + b;}

内联函数

C++中添加了一个新的关键字inline,在函数定义前加上即可将函数嵌入所有调用函数的地方,以此来消除调用函数时产生的时间开销,适用于简单且规模小的函数。
内联函数的定义非常简单,但是使用时也有一些注意点。

关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。(摘自高质量C++/C 编程指南)

参数传递

值传递

C++中的值传递与C语言中的值传递并无两样。在发生普通的函数调用时,系统会给形参分配空间并用实参的值给形参初始化。


所以,对形参的任何改动都不会对实参产生影响,需求的结果都通过返回值传回。

引用传递

引用是一种特殊类型的变量,可看作另一个变量的别称。

对引用的改动会直接反映到被引用的变量上。

函数重载

C++中的函数重载允许我们使用相同的函数名却使用不同数据类型的数据与返回值,在进行函数调用的时候,编译器会自动根据数据类型选择合适的函数。

普通的函数重载

一般的函数重载要求我们为每一个数据类型写一个函数,函数名相同,只有参数的数据类型和返回值的数据类型不同。
比如我要实现一个add函数,可以对doubleintcomplex实现相加操作。

#include <complex>#include <iostream>using namespace std;int add(int, int);double add(double, double);complex<double> add(complex<double>, complex<double>);int main(){ int a = 1, b = 5; double x = 1.12, y = 5.36; complex<double> m{2.2, 5.4}; complex<double> n{3.5, 2.1}; cout << add(a, b) << endl; cout << add(x, y) << endl; cout << add(m, n).real() <<"+"<< add(m, n).imag() <<"i"<< endl; return 0;}int add(int a, int b){ return a + b;}double add(double a, double b){ return a + b;}complex<double> add(complex<double> a, complex<double> b){ return a + b;}

就可以实现这样的输出,函数的使用更加符合人们日常生活中的逻辑了。

用函数模板实现函数重载

还是觉得麻烦?

C++中有一个更方便的方法,就是使用函数模板。但是函数模板有它的缺点,就是只有除了数据类型不同,其他代码一模一样的函数才能使用函数模板合并,我们上文中例子里的三个函数刚好都符合,那么就可以使用函数模板将他们合并。

#include <complex>#include <iostream>using namespace std;template <typename T>T add(T a, T b){ return a + b;}int main(){ int a = 1, b = 5; double x = 1.12, y = 5.36; complex<double> m{2.2, 5.4}; complex<double> n{3.5, 2.1}; cout << add(a, b) << endl; cout << add(x, y) << endl; cout << add(m, n).real() <<"+"<< add(m, n).imag() <<"i"<< endl; cin.get(); return 0;}

这样,我们只需要写一遍逻辑就可以多处重复使用,代码也更加简洁易读。事实上用函数模板写的函数在使用时也可以指定数据类型add<typename>(),但为了方便使用,我们一般让编译器从传递给函数的实参推断类型参数,这一功能被称为模板实参推断

C++系统函数

除了直接可以根据需求写出我们自己的函数,C++的系统库为我们提供了几百个函数。要使用它们,只需要将函数所在的头文件包含进我们直接的源文件中,便可以直接调用。要知道函数所在的头文件或者想知道C++是否提供了想要的函数,都可以访问cppreference网站查询。