admin 管理员组

文章数量: 1087649


2024年12月29日发(作者:开源云平台)

本文作者:黄邦勇帅

本文是学习C++的基础内容,在学习C++之前就应该完全弄清楚函数是怎么回事,本文详尽的介绍了函数的各种情况及

作用,本文是对函数未了解透彻的读者的最好选择,本文内容全面,简单易懂。

本文内容完全属于个人见解与参考文现的作者无关,其中难免有误解之处,望指出更正。

声明:禁止抄袭本文,若需要转载本文请注明转载的网址,或者注明转载自“黄邦勇帅”。

主要参考文献:

1、C++..第五版.中文版[美]Stephen Prata著孙建春韦强译人民邮电出版社2005年5月

2、C++..第四版.中文版Stanley n、Barbara 著李师贤等译人民邮电出版社2006年3月

3、C++..第三版.中文版Stanley n等著潘爱民张丽译中国电力出版社2002年5月

4、C++入门经典第三版[美]Ivor Horton著李予敏译清华大学出版社2006年1月

5、C++参考大全第四版[美]Herbert Schidt著周志荣朱德芳于秀山等译电子工业出版社2003年9月

6、21天学通第四版C++ [美]Jesse Liberty著康博创作室译人民邮电出版社2002年3月

12.函数

12.1函数原型

在C++中所有函数都必须在使用之前进行声明.函数原型除

了没有函数体外,它与函数的定义一样.函数原型指定3个

方面的内容,函数的反回类型,函数的参数类型,参数数量.

在首次调用函数之前编译器需要知道这3方面的信息,所以函

数原型应放在main函数之前.声明一个函数时可以不用参数

名,所以定义函数时可以使用与函数原型不同的参数名.

例:int hyong (int i,int j,int k);

//注意:返回类型不能是数组,声明函数原型,必须有

//分号,函数hyong的反回类型为int

void mibaoqi(int i);//声明一个不反回值的函数

main ()

{int x=10, y=11, z=2,n;

n=hyong (x,y,z); //调用函数hyong,且将hyong

//的反回值赋给变量n;

mibaoqi (x); //调用无反回类型的函数mibaoqi

cout<

int hyong (int i, int j, int k)//定义函数体

{int m;

return m=x*y*z; //使用return语句反回值;

/* return语句的反回类型必须与hyong的反回类型相兼

容,函数遇到return语句则反回到调用处*/

m=20;} //此语句被忽略,因为在return后的语

//句将被忽略

void mibaoqi (int i)

{int x; x=i; cout<

return; } //无反回值的return语句,注意分号

12.2函数通式.

函数通式为:反回类型函数名(参数列表) {语句}

如void hyong (int i,int j){语句},就定义了一个名为

hyong的无反回类型的函数,该函数有两个参数,参数

之间用逗号分开.注意:函数的反回类型不能是数组.不

能在一个函数中定义另一个函数

12.3使用return反回值

函数遇到return语句,正在执行的程序就会立即返回到其调用

函数所在的位置,函数的其他代码将被忽略.一个函数可以包

含几个return语句,一旦遇到return语句,函数就会反回.

如果有返回值的函数遇到结束的大括号而返回,那么就会返回一个未定义的值(即未知值).可以将有反回值的函数的反

回值赋给一个变量,当没有变量接收这个反回值的时候,这个函数仍反回值,但这个值被丢弃了.

return语句有两种形式,一种不返回值,形式为return;注意后面有一个分号,使用此语句,可把函数声明为反回void类

型,即函数无反回值.另一种为返回值,形式为return 要反回的值;

注意:函数的返回值的类型必须与函数的反回类型相兼容.

12.4函数的参数

12.4.1 形参和实参

传递给函数的值称为实参.定义函数时声明的接受函数实参的变量称为形参.

12.4.2 参数的传递方法

例:值调用和引用调用对实参的影响

void swap (int x, int y) //交换实参的值

参数的传递方法有值传递和引用调用两种,其中值调用是

void swap(int *x, int *y)

将实参的值复制到形参中,因此形参的变化不会对实参产

生影响,而引用调用是将实参的地址而不是值传递给形参,

main()

{ int i=10, j=20; cout<

因此形参指向调用实参的地址,形参的变化就会影响到调

swap ( i, j); //值调用,不会交换实参的值

用函数的实参.

cout<

引用调用

swap (&i , &j) //引用调用,将交换实参的值

1.传递指针实参

要传递指针类型的实参,则形参就必须声明为指针类型,

cout<

void swap (int x, int y)

参数传递时是将实参的地址传递给形参,所以当使用指

{ int temp; temp = x; x=y; y=temp;}

针的函数执行操作时,是在对指针所指向的变量进行操

void swap (int *x, int *y)

作,因此函数可以改变实参的值

{ int temp; temp =*x; *x=*y; *y=temp;}

2.传递数组实参

//此函数会改变实参的值,因为形参是指向实参的指针,对

在给函数传递数组参数时,传递的是数组的第一个元素

形参的操作就是对指向实参地址的变量的操作

的地址,而不是整个数组的一个副本.这意味着形参必

须声明为兼容的类型.有3种方法可以声明接受数组的

例:传递数组

void f (int x[10]); //将形参声明为具有相同容量和类型

形参.

//的数组,在这里形参接收的是实参的

a.将形参声明为一个数组.这个数组和调用函数时使用的

//址址,而不是整个数组的值

数组具有相同的类型和容量.在这种方式中,即使形参

具有和实参相同的整型数组,C++编译器也也会将其转换

void f (int x[]); //将形参声明为没有大小的数组,这种

//类型也是接收的实参的地址

成int指针.因为没有形参可以实际接收整个数组.由于

只传递数组的指针,所以必须有一个指针参数接收它.

void f (int *x); //将形参声明为一个指针

main ()

b.将形参声明为一个没有大小的数组.这种类型也是接

{ int t [10], i; for (i=0;i<10;++i) t[i]=i; f (t); }

收的实参的地址

c.将形参声明为一个指针.这是编写C++程序的常用方法.

void f ( int x[10]) //f函数定义相同,只是形参形式不同

3.传递字符串实参

{for (int i=0;i<10;i++) cout<

在将字符串传递给函数时,实际上只传递指向字符串开头处的指针.形参应声明为char *类型的指针.

4.引用类型的形参

a.使用引用类型的形参时,会自动将实参的地址(不是值)传递给形参,在函数中对引用参数操作被自动解除引用,

所以不需要使用指针运算符

b.声明引用类型的形参的方法为在形参变量的名称前加上&运算符就可以声明引用类型的形参了,对引用参数的

操作会影响到实参的值,而不是引用参数本身.

例:引用类型的形参例:使用引用形参交换实参的值

void swap (int &x, int &y);

void f (int &i); //声明引用类型形参的函数

main ()

main()

{int i=10, j=20; cout<

{ int x=1; cout<

f (x); //引用参数自动传递x的地址,swap(i, j); cout<

void swap (int &x, int &y)

//在x前不用加&地址引用符号

{ int temp; temp=x; x=y; y=temp;}

cout<

//交换实参i和j的值,在x和y前不用加*指针运算符,

void f (int &i) {i = 10;}

//此语句是对i所引用的变量x的操作,也就是对x赋值此语句是对x和y引用的变量i和j的操作,并不是对

10,并不是对i赋值,注意在引用类型形参的函数调用x和y的操作,在这里x和y就是i和j地址,对x和y

中i前面不用加*指针符号,在这里变量i就是一个地址的操作就是对i和j的操作

12.5返回类型为指针和引用的函数

a.如果函数的返回类型是引用,则函数的返回值是一个隐含的指针,

也就是说函数返回的是一个地址,即return语句后的反回类型不

用加地符运算符&,函数也会自动将其地址反回,例如int x; return x;

则函数会返回变量x的地址,而不是x的值.如果是返回的某个变

量的地址,则对这个函数的操作也就相当于是对这个变量的操作.

所以函数可以用于赋值语句的左边,即函数可以当作变量来使用.

b.如果函数的返回类型是指针,那么return语句中使用的值必须是与

指针相兼容,也就是说return必须反回的是地址.返回指针类型的

函数也可以当作变量来使用.

c. 千万不要反回局部对象的引用或指针。因为当函数执行完毕后,

将释放分配给局部对象的存储空间,此时对局部对象的引用或

例:返回类型为指针的函数

intj=12;int*f();

main()

{intx,y=15;

x=*f();//把f()所指向的变量的值赋给x

*f()=y;

/* 函数f当作变量来使用,此处相当于全局变量j,

即f()所指向的地址的变量j */

cout<<*f()<

/* 再次调用f,但f只反回j的值,j在前面被赋于了

15,在这里并没改变全局变量j的值,所以输出15 */

();}//暂停,等待用户按回车

int*f()

{return&j;}

//应反回地址以与指针兼容

指针就会指向不确定的内存。

例:返回类型为引用的函数

//注意此处声明全局变量并赋值

intj=12;int&f();

main()

{intx,y=15;

x=f();//把f()引用的变量j的值赋给x

f()=y;

/* 函数f当作变量来使用,此处相当于对f()引用的变

量赋值,注意f()前不用加*号*/

例:即使在cout<

//注意此处声明全局变量不赋值

intj;int&f();

main()

{intx,y=15;

x=f();//调用函数f,且对j赋值12.所以x的值为12;

cout<

f()=y;

//再次调用函数f.且对j赋值12.并把y的值15赋给f()引用的变量

//j,所以j现在的值为15

cout<

/* 再次调用f,但f只反回j的值,j在前面被赋于了15,

在这里并没改变全局变量j的值,所以输出15 */

cout<

cout<

/* 注意,这里将再次调用函数f,并不是直接输出f()的值,且对j再次赋值

12,j的值由先前的15变回12,然后反回f引用的变量j的值,所以输出f()的值

为12 */

}

();}//暂停,等待用户按回车

int&f(){returnj;}

//反回j的地址,此处不用加地址运算符

int&f(){j=12; returnj;}//对全局变量j赋值12

int &h() {int i=12;return i;}//错误,不能反回局部对象的引用

12.6引用变量

引用变量必须指向某些对象,因此,声明引用变量时必须进行初始化.例如int j;int &i=j; i=10;这里是把j的地址赋给

引用变量i,而i=10并不是对i赋值,而是对i所引用的变量j赋值,所以这里j被赋值为10.语句int &j;是错误的引用

变量必须被初始化.

例:函数重载

void f (int x);

12.7函数重载

函数重载,参数类型

void f (short x);

或数量必须不同

使用相同名称但参数不同的函数就叫函数重载,

void f (double x);

函数重载必须是每个重载函数的参数类型或数

void f (int x, int y);

main ()

量必须不同.调用重载的函数时,就会执行形

{ int i =10, j=11; short s=99; double d=10.1; float t=11.5F;

f (i); //调用函数f (int x)

参与实参相匹配的那个函数.

f (i, j); //调用函数f(intx, int y)

f (s); //调用匹配的函数f (short x)

12.8函数默认参数

f (d); //调用函数f (double x)

Ê.声明默认参数和声明变量相似,例如

f (t);} //调用函数f (double x)此处发生自动类型转换

void f (int x, int y) {cout<< x<

void f (int x=0, int y=90);调用方法有三种,

void f (int x) { cout<

void f (short x) {cout<

如f (1,2),将1传给x,2传给y,

f (11)将值11赋给x,y使用默认值90,f()参数x和y都使用默认值.

2.默认参数只能指定一次,并且只能在文件中首次声明函数时或函数原型中指定,例如在函数原型中指定默认参数,但

如果在函数原型中指定了默认参数,又在函数定义时指定相同或不同默认参数的值时就会出错.

3.可以为重载函数的每个版本指定不同的默认参数,即重载函数的不同版本可以有不同的默认参数.

4.接收默认值的所有参数都必须出现在不接收默认值的参数的右侧,例如f (int x ,int y=10);是正确的,但是f(int x=10, int

y);就是错误的.

5.一旦开始定义接受默认值的参数,后面就不能指定不带默认值的参数,例如f (int x, int y=10, int z)就是错误的,必须

为z指定默认参数.

6.调用函数时如果其中某个参数使用了默认值,那么这个参数之后的每个参数都必须使用默认值.例如定义函数f(int x,

int y=10, int z=12),调用函数f ( 10,,15)就是错误的.

12.9 函数重载与多义性

1.多义性:即编译器不能在两个正确重载的函数间作出先择.多义性的语句就是错误.

2.自动类型转换引起的多义性:如定义函数f (float i)和f (double i),当用语句f (11)调用时就会出现错误,函数是调用

f (float i)呢?还是f (double i)呢,对于浮点常量C++会自动转换为double型,如f (11.5)就会调用f (double i),不会出

现多义性

3.默认参数引起的多义性:如定义函数f (int i)和f (int i, int j=2),则调用语句f (10)就会出现多义性,是调用f (int i)呢还

是调用f (int i, int j=2)呢?

12.10 函数指针(即指向函数的指针) int (*hyong)()

1.int (*hyong)(int a, int b)该语句声明了一个指向函数的指针hyong注意()是必须的。hyong指向的函数带有两个int型的

形参,和int型的反回值。

2.函数指针的初始化:函数名就是函数的地址,所以在给函数指针赋值时只须给出函数名即可,函数名后不能有括号。

赋给函数指针的函数必须和函数指针有相同的反回类型,相同的形参列表,只要稍微有一点不同就不能赋值。

3.函数指针的调用:可以把函数指针当函数名一样使用来调用函数,即可以这样调用函数指针hyong(4,5),还有种形式

为(*hyong)(4,5)

作者:黄邦勇帅


本文标签: 函数 类型 引用 参数 声明