2.6、函数原型
函数原型的三个特殊的任务:
(1)确定函数返回值,使编译程序能产生的函数返回数据类型的正确代码。
(2)确定了函数使用的参数的类型,个数和顺序。
(3)函数名代表该函数的函数体以及函数完成的功能。
函数的定义格式为:
函数原型
{
函数体
}
函数原型一般的语法形式为:
返回类型 函数名(参量表)
如果一个函数先使用,而后定义的话,则需要对该函数进行声明。函数声明的格式为: 函数原型;
如:int func(int a,int b);
void draw(float x,float y);
函数声明中的参数名字可以省略。
上述声明可以写为
int func(int,int);
void draw(float ,float );
C++语言需要所有函数都有原型,没有原型,则无法编译C++程序。函数原型使得C++语言能够提供更强的类型检查,它允许编译程序对下列情况给出错误信息:
(1) 被调用函数的参数类型定义和类型转换非法。
(2) 函数的参数个数不相符。
(3) 函数不能返回预定的数据类型。
由于所有C++函数都有函数原型,使得C++语言容易表达重载一个函数名的概念,亦即它能区分多个函数,它们具有相同的名字但有不同的参数。
C++语言允许进行函数重载:多个函数具有相同的函数名,但有不同的参数表和各自的函数体。只要编译能区分参数表,就可以重载一个函数名。例如:double abs(double num)
{
return((num<0)? – num : num);
}
long abs(long num)
{
return((num<0)? –num : num);
}
这样,就有了函数的重载,两个函数,它们具有相同的函数名abs,但有不同的参数类型(long和double)。
2.7、缺省参数
C++语言有缺省参数的概念,它是另外一种形式的重载。
void fun(int num=0)
{…}
num称为缺省参数,0称为缺省值。调用函数fun时,num对应的实参可以有,也可以没有,可以调用两种方式调用函数fun:
fun(10); // 传递显示的值,则num 的初始值为10
fun(); // 无对应的实参,则num的初始值为0
一个函数含有的参数常常比它最常用的方法所需的参数还多。例如:
#include "conio.h"
#include "iostream.h"
void xyout(char * str, int x=-1,int y=-1)
{
if (x==-1) x=wherex();
if(y==-1) y=wherey();
gotoxy(x,y);
cout<<str;
}
void main()
{ char *str0="Hello world";
xyout( str0, 2,20);
xyout( str0, 20);
xyout( str0);
}
需说明的是,所有取缺省值的参数都必须出现在不取缺省值的参数的右边。亦即,一旦开始定义取缺省值的参数,就不可以再说明非缺省的参数。例如:
对于函数 void fun(int x=10,int y); ?
则函数调用
fun(a); //错误,因为a位置上对应 x,而y不是缺省参数,必须有对应的实参。在使用具有缺省参数的函数时,若该函数名还被重载,要谨防二义性。
例如:
void func(int x=1)
{
…
}
void func()
{
…
}
则函数调用
func();
就不知是调用那个函数了。
2.8、引用
引用简单地说,就是给一个变量取一个别名。引用与它所用的变量共享存储单元。引用主要有以下三个途径:
1、独立引用
引用表示为:
TYPE&, 它的含义为"TYPE类型的引用"。
TYPE &ref_name=TYPE的一个变量;
由于一个引用变量必须引用指向某一变量,独立引用必须在它被说明时加以初始化,初始化分为两种情况:
1)初始化时,赋值表达式的右端是一个变量。例如
int & rr=ii; //ii 是一个变量
2)初始化时,赋值表达式的右端是一个常量值。例如
double & rd=1.0;
double & rd=1.0;在早期是允许的,但最近版本中,引用与一个常量相联系,使用
const double & rd2=1.0; 表示,表明rd 引用的是一个常数单元,不能被赋值,这样语义更明确。
还可以定义常引用。
int x=1;
const int & rx=x;
rx=120; //错误,只能使用rx,不能修改
2、引用作为函数参数
C语言采用传值方式进行参数传递。当一个函数需要修改对应的实参的值时,参数应定义为指针类型。
总之,C++有两种传值方式:直接传值,传地址(通过指针变量或引用)
在有些文献中,认为C语言只具备直接传值的函数传值方式,而不具备传地址的方式,因为,他们认为,传指针变量,实质上仍然是一种值传递,而只有引用才能真正称得上是地址传递。
3、引用作函数的返回
函数返回引用,实际上返回的是一个存储单元,因此,如果一个函数返回引用的话,则函数调用可以出现在赋值号的右边,也可以出现在赋值号的左边。
#include<iostream.h>
int& get_var(int* pint)
{
return* pint;
}
int main()
{
int anint=10;
int otherint;
otherint=get_var(&anint)*12;
get_var(&anint)=200;
cout<<otherint<<" "<<anint;
}
函数返回引用,那么,return后面应该为引用。除了独立引用外,还可以是:
数组元素
static变量
指针所指向的变量,即*p
结构的分量
联合的分量