C++基础之函数

0
13

一、函数参数的默认值

C++语言规定,提供默认值时必须按从右至左的顺序提供,即有默认值的形参必须在形参列表的最后。如果有某个形参没有默认值,则它左侧的所有形参都不能有默认值。调用函数时,主调函数的实参与被调函数的形参按从左至右的顺序进行匹配对应。

// 为参数a,b,c分别设置了默认值11,22与33
void func(int a=11,int b=22,int c=33){
    cout<<"a=" <<a<< ",b="<<b<<",c="<<c<<endl;
}
int main() {
    func(); //调用时缺少了3个实参,将使用定义中的3个参数默认值
    func(55); //调用时缺少了后2个实参,将使用定义中的后2个参数默认值
    func(77,99); //调用时缺少了最后1个实参,将使用定义中的最后1个参数默认值
    func(8,88,888); //调用时实参完备,将不使用定义中的任何参数默认值
    return 0;
}

二、函数的调用

假设给出如下的函数声明:
void func(int a,int b=2,int c=3);
则下列函数调用中哪些是正确的?请解释原因。
//正确
func(1,22,333);
//错误因为第一个参数没有默认值
func();
//正确
func(10,20);
//错误的,调用时给出的实参应该是连续排列的
func(5,,9);

三、引用和函数参数的传递

1. 引用的定义
引用相当于给变量起了一个别名。变量对应于某个内存地址,如果给某个变量起了别名(不需要给它另开辟内存单元),相当于变量和这个引用都对应到同一地址。程序中使用哪个名字都是允许的。在C++中,
C++中“引用”的定义格式:类型名 &引用名=同类型的某变量名;

int main() {
    int num=100;
    int &num_r=num;
    cout<<" &num_r=" <<num_r<< ",numb="<<num<<endl; // &num_r=100,numb=100
    num=101;
    cout<<" &num_r=" <<num_r<< ",numb="<<num<<endl;// &num_r=101,numb=101
    num_r=102;
    cout<<" &num_r=" <<num_r<< ",numb="<<num<<endl;// &num_r=102,numb=102
    return 0;
}

2、应用数据作为函数参数

在程序中不仅能定义变量的引用,还可以将引用用在函数中。引用既可以作为函数的参数使用,也可以作为函数的返回值使用。

 int& add(int &a){
    a++;
    return a;
}
int main(){
    int mun=8;
    int &a=mun;
    int &m=add(a);
    cout << "num=" << mun <<endl; //num=9
    m++;
    cout << "num=" << mun <<endl; //num=10
    return 0;
}

在C++中,函数调用时参数的传递有两种方式:传值和传引用。

  • 传值,实际上是传递对象的值。传引用是传递对象的首地址值。如果函数的形参不是引用,那么调用时实参传递给形参通常采用的是传值的方式,即将实参的值拷贝给形参。在函数执行过程中,都是对这个拷贝进行操作的,函数执行完毕返回后,形参的值并不拷贝回实参,也就是说函数内部对形参的改变不会影响到函数外实参的值。
  • 如果函数的形参是引用,则调用时实参传递给形参采用的是传引用的方式。函数调用时,实参对象名传递给形参对象名,形参对象名就成为实参对象名的别名,即形参是对应实参的引用,它们是等价的,代表同一个对象,也可以看作是将实参的地址传递给了形参。在函数内部对形参的操作,都是对这个地址的内容进行的,相当于对实参的值进行了操作。所以当函数执行完毕返回后,实参的变化被保留下来。
//传值 a、b值互换
void SwapValue(int a,int b){
    int tmp;
    tmp=a;
    a=b;
    b=tmp;
    cout<<"SwapValue=>a="<<a<<",b="<<b<<endl;//SwapValue=>a=20,b=10
}
//传引用 a、b值互换
void SwapRef(int & a,int & b){
    int tmp;
    tmp=a;
    a=b;
    b=tmp;
    cout<<"SwapRef=>a="<<a<<",b="<<b<<endl;//SwapRef=>a=20,b=10
}
int main(){
    int a=10,b=20;
    cout<<"a="<<a<<",b="<<b<<endl<<endl;//a=10,b=20
    SwapValue(a,b);
    cout<<"SwapValue() a="<<a<<",b="<<b<<endl<<endl;//SwapValue() a=10,b=20
    a=10;
    b=20;
    SwapRef(a,b);
    cout<<"SwapRef() a="<<a<<",b="<<b<<endl<<endl;//SwapRef() a=20,b=10
    return 0;
}

四、内联函数:inline

1、为了避免这种频繁的函数调用与返回,C++语言引入了内联函数的概念。使用内联函数,编译器在编译时并不生成函数调用,而是将程序中出现的每一个内联函数的调用表达式直接用该内联函数的函数体进行替换,就像整个函数体在调用处被重写了一遍一样。很显然,使用内联函数会使最终可执行程序的体积增大。这是以空间消耗节省时间开销。
2、内联函数应该定义在前,调用在后,定义时只需在函数头返回值类型的前面加上关键字inline。
3、内联函数主要应用于代码量少的函数,频繁调用;
4、如果函数体中有循环语句和switch语句则通常不定义为内联函数。

//inline 定义函数
inline int add(int a){
    return a+a;
}
int main(){
  int a=10;
  a=add(a);
  cout <<"a:="<<a <<endl;
  return 0;
}

五、函数的重载

所谓函数重载,是指在程序的同一范围内声明几个功能类似的同名函数。实现函数的重载必须满足下列条件之一:

  • 参数表中对应的参数类型不同。
  • 参数表中参数个数不同。

如果函数参数表中不同类型参数的次序不同,也符合上面所说的条件。要注意的是,返回值类型不能用来区分函数,也就是说,如果两个函数的名字和参数表都是一样的,仅仅是返回值类型不同,则这两个函数不是重载的,编译器认为它们是重复定义,编译时会报错。

int add(int a){
    return a+a;
}

int add(int a,int b){
    return a+b;
}

int add(int a, double b){
    return a+b;
}

double add(double a, double b){
    return a+b;
}
int main(){
    int a=10;
    a=add(a);
    cout <<"a:="<<a <<endl;
    a=add(a,a);
    cout <<"a:="<<a <<endl;
    a=add(a,10.1);
    cout <<"a:="<<a <<endl;
    a=add(10.4,10.6);
    cout <<"a:="<<a <<endl;
  return 0;
}

为什么不能使用返回值类型作为重载:重载发生在编译阶段,而返回值是运行阶段;如果仅仅是返回值类型不同,编译器是无法区分具体调用哪个函数的

传值参数与引用参数也不能区分函数,无法重载:

void print(double);
void print(double&);//错误

<

发布回复

请输入评论!
请输入你的名字