6.函数
6.1 函数的定义和调用
6.1.1 函数的定义
C++中,函数的定义形式;
返回值类型 函数名 (参数1类型 参数1名称,参数2类型 参数2名称,… )
{
语句组(“函数体”)
}
6.1.2 函数的调用
函数名(参数1,参数2,…)
6.2 函数的声明
函数的定义必须在函数调用语句之前,否则调用语句在编译时就会报“标识符(就是函数名)”没有定义的错误。
有些比较复杂的程序是由多个.cpp文件构成,可能不止一个文件调用了某个函数,但是函数的定义在整个程序中只能出现一次,这时候就要用到“函数的声明”来使编译通过。
还有种情况,两个函数互相调用,显然无论把哪个函数的定义写在前面都是不合理的,这个问题也可以用“函数的声明”来解决。
函数的声明,即指不写出具体的函数体,只写出函数的名称、返回值类型和参数表,即只编写函数的“原型”。
返回值类型 函数名 (参数1类型 参数1名称,参数2类型 参数2名称,… )
实际上,函数声明中的参数名称可有可无,关键表明参数的类型即可。
返回值类型 函数名 (参数1类型 ,参数2类型 ,… )
6.3 main函数
C++函数都是从main函数开始执行的。执行到main函数中的return语句时,整个程序就结束了。main函数的返回值,对程序本身没有什么用处,但对启动搞程序的程序(通常是操作系统)会有用。
6.4 函数参数的默认值
在声明一个函数时,可以为函数的参数制定默认值。那么当调用有默认参数值的函数时,可以不写参数,相当于以默认值作为参数调用该函数。
在指定默认值时不仅可以用常数来指定,而且可以用任何有定义的表达式来作为参数指定默认值。
函数参数的默认值,可以编写在声明函数的地方,或者编写在定义函数的地方,但是不能在两个地方都编写。
省略的参数一定时最右边连续的几个,不能缺省开始或中间的几个参数值。
void Function1(int x = 20); //函数的声明中,致命参数x的默认值为20;
...
Function1(); //调用语句,参数缺省,等效于Function(20);
/***********************/
int Max(int m, int n); //声明Max函数;
int a, b;
void Function2 (int x , int y = Max(a, b), int z = a * b) //Function2 函数定义;
{
...
}
Function2(4); //正确,等效于Function2(4,Max(a,b), a * b);
Function2(4,9); //正确,等效于Function2(4, 9,a * b);
Function2(4,2,3); //正确;
Function2(4, ,3); //错误!!!省略的参数一定是最右边连续的几个;
6.5 引用和函数参数的传递
6.5.1 引用
引用,实际上某个变量的引用和这个变量是一回事,只是相当于该变量的一个别名。主要用于函数传参和做函数返回值。
定义方式:
类型名 & 引用名 = 同类型的某变量名;
int n;
int & r= n;
创建了n的一个引用:r;r的类型为 int &。
一定注意!!!
1.定义引用时一定要将其初始化,否则编译无法通过,而且其无法再引用其他变量。
2. 只能用变量初始化。可以用变量去初始化引用,还可以用引用去初始化引用,这样两个引用就引用同一个变量了。但是不能用常量来初始化引用。
3. T&类型的引用和类型为T的变量之间是完全兼容的,可以相互赋值。
#include <iostream>
using namespace std;
int main(){
int n = 4;
int & r = n; //创建n的引用r;
r = 4;
cout << r << endl; //4;
cout << n << endl; //4;
n = 5;
cout << r << endl; //5;
int & r2 = r;
cout << r2 << endl; //5;
return 0;
}
6.5.2 引用作为函数返回值
函数的返回值可以是引用,有些类似于指针的用法,一个函数的返回值是引用的话,那么就可以将其作为左值进行赋值。当然其还有其他的用法,如“运算符重载”。
#include <iostream>
using namespace std;
int n = 4; //定义全局变量;
int & SetValue()
{
return n; //SetValue函数返回指向全局变量 n 的引用;
}
int main(){
SetValue() = 40; //相当于 n = 40;
cout << n << endl;
int & r = SetValue(); //相当于 int & r = n ; 用n的引用对int &类型的引用 r 进行初始化;
cout << r << endl; //40;
return 0;
}
6.5.3 引用用于函数传参
6.5.3.1 参数传值
如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
当调用函数时,有三种向函数传递参数的方式:
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值赋值给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。 |
指针调用 | 该方法把参数的地址赋值给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
引用调用 | 该方法把参数的引用赋值给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
6.5.3.1 参数传引用
在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。
#include <iostream>
using namespace std;
void Swap(int & a, int & b)
{
int tmp;
tmp = a; a = b; b = tmp;
return;
}
int main(){
int n1 = 100, n2 = 200;
Swap(n1, n2);
cout << n1 << ',' << n2 << endl; //输出200,100
}
6.5.4 常引用
在定义引用之前加“const”关键字,这样就定义了一个“常引用”。
int n;
const int & r = n;
常引用和普通引用之间的区别在于,常引用不能被用来修改其引用的内容。注意:不是常引用所引用的内容不能被修改,只是不能通过直接修改常引用来进行修改,而是要通过修改“本体”来进行修改。比如,上述两行代码中,定义了n的一个常引用r,可以修改n的值,同时r的值也会被修改,如果妄图修改r的值来修改n的内容,这样是不合法的。
int n = 100;
const int & r = n;
r = 200; //编译出错,不能通过常引用修改其引用的内容;
n = 200; //正确!
还应注意的一点!!
T& 类型的引用或者 T或者 const T 类型的变量可以用来初始化 const T& 类型的引用;
const T 常量和 const T& 常引用不能用来初始化 T & 类型的引用,除非进行强制类型转换。
#include <iostream>
using namespace std;
int main(){
const char cc = 'a';
char c;
const char & rc1 = cc ;
const char & rc2 = c; //char可以初始化const char &;
char & r = cc; //const char不能初始化char &引用,否则就给了引用r随意修改常量cc的权限了;
char & r2 = (char &) cc; //OK;强制类型转换;
return 0;
}