函数重载与引用【C++】

函数重载

函数重载允许函数间可以重名,在函数调用时,不再单单以函数名来寻址调用,而是函数名加参数类型及其顺序来调用的,这方便了一些函数的命名。
例如要实现整型之间的交换,以及浮点型之间的交换:
用C语言写时,得想两个不同函数名,由于又都是实现交换,两个函数名也一般只有前后缀的区别,一来二去使得实现时麻烦,在调用时也麻烦,你看我解释估计都会嫌麻烦;
但用C++来实现的话就少很多事了,两个函数的函数名都写Swap,后面参数按需求写就行,就少了不少烦心事,代码如下:

void Swap(int* num1, int* num2)
{
	int tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}

void Swap(double* num1, double* num2)
{
	double tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}

int main()
{
	int num1 = 3;
	int num2 = 6;

	double _num1 = 1.1;  // 变量就不支持重名了哦
	double _num2 = 2.2;

	cout << "交换前" << endl;
	cout << num1 << " " << num2 << endl;
	cout << _num1 << " " << _num2 << endl;

	Swap(&num1, &num2);  
	Swap(&_num1, &_num2);
	
	cout << "交换后" << endl;
	cout << num1 << " " << num2 << endl;
	cout << _num1 << " " << _num2 << endl;

	return 0;
}

这里利用重载就解决了一些烦心事

函数重载的注意点

不同的函数返回类型不能构成函数重载,构成函数重载的条件有三个:函数名,参数类型及其顺序。
我们站在编译器的角度看下重载是怎么实现的,对于每个函数,编译器都会生成一个名称,对于C语言,这个名称只与函数名有关,而C++中这个生成的名称与函数名,参数类型及其顺序有关,这就使得后续汇编和链接、以及调用时能够做出区分。

引用

上面的Swap()函数调用起来是不是有点别扭?指针变量用起来是不是有点难受?这里介绍一下指针的兄弟—引用&。
先看下&的效果,再进行讲解:

// 指针版
void Swap(int* num1, int* num2)
{
	int tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}

// 引用版
void Swap(int& num1, int& num2)
{
	int tmp = num1;
	num1 = num2;
	num2 = tmp;
}

void Swap(double& num1, double& num2)
{
	double tmp = num1;
	num1 = num2;
	num2 = tmp;
}

int main()
{
	int num1 = 3;
	int num2 = 6;

	double _num1 = 1.1;  // 变量就不支持重名了哦
	double _num2 = 2.2;

	cout << "交换前" << endl;
	cout << num1 << " " << num2 << endl;
	cout << _num1 << " " << _num2 << endl;

	//Swap(&num1, &num2);  
	//Swap(&_num1, &_num2);
	Swap(num1, num2);
	Swap(_num1, _num2);

	cout << "交换后" << endl;
	cout << num1 << " " << num2 << endl;
	cout << _num1 << " " << _num2 << endl;

	return 0;
}

用了引用之后是不是清爽了许多,有人可能会问:“&用来做引用了,那哪个符号是取地址呢?”C++是向前兼容C语言的,你要相信C++之父,&在C++中有了多重意思,就像函数能重载一样,如果是 类型名&,如int&、double&、自定义类型& 等,这里的&就是引用的意思;而&变量,这里的&还是取地址的功能。
阅读以下代码,猜猜输出多少:
A. -1 1 B. 0 0

	int a = 0;
	int& x = a;

	a--;
	x++;

	cout << a << " " << x << endl;

恭喜蒙B的同学答对了!
笔者称引用是指针的兄弟是因为,在底层的汇编指令中,引用和指针的指令是一样的,只不过在语法上引用用起来是更方便的,不需要刻意传址传参,并在想修改实参时,不需要额外*解引用形参,直接对形参做对应操作即可,还有就是引用不用额外地开辟空间,相对于指针而言能节省一部分的空间。
在这里插入图片描述

int& x = a的意思就像是给a取了一个外号叫x,既然是外号,那a和x就是指同一个变量,就像鲁迅和周树人是同一个人一样,通过取地址可以发现,a和x的地址是一样的,即a和x管理着同一块空间,那么x改变a也会跟着改变,反之a变x也会变,这跟C语言中的联合体有点像,区别就是引用时,要求二者的类型要相同。
sizeof(外号)和被引用对象的大小是一样的,而不是和地址大小有关,这也就验证了外号和指针变量是不同的。
需要注意的是引用时必须要有对象,并且外号在给定某一个对象后,就不允许把这个外号给别人了,从用法上也更改不了,就像这样是行不通的:

	int a = 0;
	int b = 0;
	int& x = a; // 给a取外号叫x 
	int& x = b; // 突然想把外号给b了
	// 在计算机的世界里,外号x就是个变量,是变量就不允许多次定义
	// 这就是引用较指针而言不同的地方,指针变量可以通过赋值修改指向对象

有同学可能会说我这样行不行:

	int a = 0;
	int& x;  // 先定义一个外号,但不初始化
	x = a;   // 给a取外号x
	int b = 0;
	x = b;	// 再给b取外号x

答案是不行的,语法要求引用时必须要初始化,不能单单定义外号但不给确定的人或对象,引用但不给具体的引用对象,就像调用函数没给参数一样,假设&是一个函数,int& x = a,就相当于int& x = &(a);我想表达的意思是引用时如果没有外号x是可以的,但没有a就是不行的了,因为a才是那个被引用的对象。

引用传参

void Swap(int& num1, int& num2)
{
	int tmp = num1;
	num1 = num2;
	num2 = tmp;
}

// 调用时
Swap(num1, num2); // 不取地址真能完成交换?

这里不取地址传参也行的原因是函数参数用了引用&,传参的效果就相当于:int& num1(形参) = num1(实参),这样一来,实参和形参就是指同一个对象了,在背调函数体内改变形参,就相当于改变实参,于是就可以完成交换效果。

引用返回值

如果一个要返回的对象在出了被调函数后,生命周期没有结束,此时就可以考虑用引用该对象进行返回,格式如下:

int& Add(int& num1, int num2)  // 
{
	num1 += num2;
	return num1;  // 不直接写return num1 + num2;是因为此时是引用返回,引用返回要有具体的对象且该对象在出了函数域后仍然存在
}

int main()
{
	int a = 1;
	int b = 2;
	int& c = Add(a, b);
	cout << a << endl;

	c -= b;

	cout << a << endl;
	return 0;
}

由于还没学类和对象,这里还不好讲合适的应用场景,后续写运算符重载、类中的赋值重载等类似的东西时,引用返回的作用就很明显了,目前来说引用返回的作用就是能减少拷贝带来的花销。

总结

一个词有多个解释就构成了这个词的重载,本篇文章就讲了重载在函数中的应用,其实运算符也能重载,比如自定义结构体本没法进行加减乘除等运算,我们可以重载内置运算符的使用来达到,后续会总结,另外注意函数重载的三个条件,返回类型不同不构成重载哦。
引用就是给被引用对象取外号,然后直接用外号就能影响该对象,引用和指针是俩兄弟,没有什么……引用能完全替代指针的说法,因为二者各有特点优势,一个指针变量随时可以修改指向的对象,而外号只能和一个对象从始至终绑定在一起,这样也让引用用起来比指针更安全,不会出现访问野指针的风险,在具体使用场景中选合适即可;引用在目前的作用就是减少拷贝带来的花销,这和指针能带来的效果差不多,既然C++之父要可以设计引用,就说明它的作用不止于此,后续笔记中还会出现引用的,到时便能体会引用的好处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值