函数(C++)

2023-12-20 22:05:37

1.7 函数

1.7.1 函数缺省参数

在C++中,函数的形参列表中的形参是可以有默认值的。有默认值的参数即为默认参数。

在函数调用时,有默认参数可以缺省。

语法:返回值类型 函数名 (参数= 默认值){函数体}

#include <iostream>
using namespace std;

int add(int x, int y, int z = 100) {
	return x + y + z;
}

int main(void) {
	
	cout << add(3, 3) << endl;		//106
	cout << add(3, 3, 4) << endl;	//10
	return 0;
}

注意事项:

  • 靠右原则:如果某个位置参数有默认值,那么从这个位置往后,从左往右,必须都要有默认值。
#include <iostream>
using namespace std;

int add(int x, int y = 100, int z) { //error
	return x + y + z;
}

int main(void) {
	
	cout << add(3, 3) << endl;
	cout << add(3, 3, 4) << endl;
	return 0;
}

  • 函数声明和函数实现(即函数定义),只允许其中一个有默认值,即如果函数声明有默认值,则函数实现的时候就不能有缺省参数。
#include <iostream>
using namespace std;

int add(int x, int y, int z = 100);//声明这有默认值了

int main(void) {
	
	cout << add(3, 3) << endl;
	cout << add(3, 3, 4) << endl;
	return 0;
}

int add(int x, int y, int z) { //定义这就不能再有了
	return x + y + z;
}

1.7.2 哑元

只有类型而没有变量名的参数成为“哑元”。

int func(int a, int ) {
    ……
}

需要使用哑元的场景:

  • 兼容旧代码,保证函数的向下兼容性
void func(int i, int j){...}==升级==>void func(int i){...}
void func(int i, int j){...}==升级==>void func(int i, int /*哑元*/){...}
  • 操作符重载中,区分前后++/- -

1.7.3 引用参数

  • 可以将引用用于函数的参数,这时形参就是实参的别名

  • 引用型函数参数作用

    • 在函数中修改实参的值

      #include <iostream>
      using namespace std;
      
      void swap(int &, int &) ;
      
      int main (void) {
      
      	int x = 100;
      	int y = 200;
      	swap(&x, &y);
      	cout << "x : " << x << "\t" << "y : " << y << endl;
          getchar();
      	return 0;
      }
      
      void swap(int &a, int &b) {
      	int temp = a;
          a = b;
          b = temp;
      }
      
      
    • 避免实参到形参数值复制的开销,提高传参效率

      #include <iostream>
      using namespace std;
      
      struct Teacher{
      	char name[100];
      	int age;
      };
      
      void print(Teacher &st){
      	cout << st.name << ',' << st.age << endl;
      }
      
      int main(void) {
      	Teacher st = {"王钢蛋", 18};
      	print(st);
      	return 0;
      }
      
  • 引用型函数参数可能意外修改实参,如果不希望通过引用修改实参本身,可以将其声明为常引用(const),在提高传参效率的同时还可以接收常量型实参

      #include <iostream>
      using namespace std;
      
      void add(const int &x, const int &y){
      	// x++; //error
      	cout << "x + y = " << x+y << endl;
      }
      
      int main (void) {
      	int x = 3, y = 5;
      	add(x,y);
      
      	return 0;
      }
      
    

1.7.4 返回引用

  • 可以将函数的返回类型声明为引用型,这时函数的返回结果就是return后面数据的别名,避免了函数返回值的开销

  • 函数中返回引用,一定要保证在函数返回以后,该引用的目标依然有效

    • 可以返回全局变量、静态变量和成员变量的引用
    • 可以返回引用型参数的本身
    • 可以返回调用对象自身的引用
    • 可以返回堆中动态创建的引用
    • 不能返回局部变量的引用 / 非常危险
    #include <iostream>
    using namespace std;
    
    int &add(int &a, int &b) {
    	int temp = 0;
    	temp = a+b;
    	return temp; //风险 局部函数结束时内存空间回收
    }
    
    int main(void) {
    
    	int x = 3, y = 5;
    	
    	int &t = add(x,y);
    	t++; //通过别名操作 已经被系统回收的内存
    	cout << t << endl;
    	return 0;
    }
    

1.7.5 函数重载

  • 基本作用

    同一作用域,函数名相同,但是当中的参数必须有所区分(类型、个数、顺序),将构成重载关系

    #include <iostream>
    using namespace std;
    
    void swap(int *a, int *b) {
    	cout << "a + b = " << *a + *b << endl;
    }
    
    void swap(char *a, char *b) {
    	cout << "a + b = " << *a + *b << endl;
    }
    
    
    void swap(float *a, float *b) {
    	cout << "a + b = " << *a + *b << endl;
    }
    
    int main(void) {
    
    	int a = 3, b = 5;
    	swap(&a, &b);
    	
    	char c1 = 'a', c2 = 'b';
    	swap(&c1, &c2);
    
    	float f1 = 3.1, f2 = 3.3;
    	swap(&f1, &f2);
    	return 0;
    }
    
  • 重载的实现

    编译器将形参变量的类型作为最终函数名的一部分。

    nm a.out
    

    在这里插入图片描述

    注意

    ? 1)形参变量名不同 不构成重载的要素

    void swap(int *a, int *b);
    void swap(int *sa, int *sw); //形参变量名不同
    

    ? 2)函数返回类型不同 不构成重载的要素

    int swap(int *a, int *b);
    void swap(float *a, float *b);//函数返回类型不同
    
  • 函数匹配的优先级

    当前g++编译器匹配的一般规则:

    1)完全匹配 //最高

    2)常量转换 //良好

    3)升级转换 //一般

    4)降级转换 //较差

    5)省略号匹配 //最差

    #include <iostream>
    using namespace std;
    
    void swap(int x) {
    	cout << "swap(int)" << endl;
    }
    
    void swap(int x, int y) {
    	cout << "swap(int, int)" << endl;
    }
    
    void bar(int c) {
    	cout << "bar(int)" << endl;
    }
    
    void bar(const char c) {
    	cout << "bar(const char)" << endl;
    }
    
    void foo(int f){
    	cout << "foo(int)" << endl;
    }
    
    void foo(char c) {
    	cout << "foo(char)" << endl;
    }
    
    void hum(int i, ...) {
    	cout << "hum(int...) " << endl;
    }
    
    void hum(int i, int j) {
    	cout << "hum(int, int)" << endl;
    }
    
    int main(void) {
    
    	int x = 10;
    	swap(x);
    
    	char c = 'a';
    	bar(c); // 常量转换 char -------> const char
    
    	short s = 10;
    	foo(s); // 升级转换 short --------> int
    
    	hum(2, 3.14); // 降级转换 double --------> int
    
    	return 0;
    }
    

注意二义性问题:

  • 默认类型转换带来的二义性

    void func(unsigned int x) {
    	cout << "func(unsigned int)" << endl;
    }
    
    void func(double x) {
    	cout << "func(double)" << endl;
    }
    
    
    	
    int j = 10;
    //func(j); //g++ 编译器不知道调用那个函数了 
    func((unsigned int) j);//需要程序员自己确认需要调用那个
    
  • 缺省参数带来的二义性

    void tem(int x, int y, int z = 200){
    	cout << "tem(int, int, int)" << endl;
    }
    
    void tem(int x, int y){
    	cout << "tem(int, int)" << endl;
    }
    
    
    
    tem(20, 30) //error 
    

文章来源:https://blog.csdn.net/qq_36091214/article/details/135117414
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。