C++:函数重载,引用

本文详细介绍了C++中的函数重载、C++支持函数重载的原理,以及引用的概念、特性、使用场景和与指针的区别。讨论了缺省参数在重载中的作用,并比较了引用和指针在内存占用、自增、多级和安全性方面的差异。
摘要由CSDN通过智能技术生成

1. 函数重载

1.1 函数重载概念

C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表 (参数个数 或 类型 或 类型顺序) 不同,常用来处理实现功能类似数据类型不同的问题。

#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}
// 2、参数个数不同
void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
	cout << "f(char b, int a)" << endl;
}
int main()
{
	Add(10, 20);
	Add(10.1, 20.2);
	f();
	f(10);
	f(10, 'a');
	f('a', 10);
	return 0;
}

在这里插入图片描述
可以看到确实可以同时调用同名不同功能的函数

1.2 C++支持函数重载的原理–名字修饰

QA:为什么C语言不支持函数重载 , 而C++可以?

C语言通过函数名来查找函数地址,而C++通过修饰后的函数名来查找函数地址。

//test.h
#pragma once
void f(int x, char y);
void h(char x, int y);
//test.c
#include <iostream>
#include "test.h"
using namespace std;
int main()
{
	f(1, 2);
	h(1, 2);
	return 0;
}

生成解决方案:
在这里插入图片描述
我在test.h只声明了两个f h函数 ,在 test.c 中使用这二者不会语法错误,但并没有写函数的内容,函数没有自己的内存空间 ,程序在运行的时候就找不到这两个函数,此时生成的解决方案,可以让我们借机观察c++是如何查找函数的。


可以看到 查找 f(int,char) 的函数名为 (?f@@YAXHD@Z),而查找 h(char,int)的函数名为(?h@@YAXDH@Z),通过对比不难看出,?后面放的是原函数的名字( f 函数是f,h函数是h ), @Z前面放参数( f 函数是HD , h函数DH )。


由此可见,C++查找函数时, 会先对函数名进行修饰,通过不同的成员变量,来区分的同名的函数

1.3 缺省参数与重载

QA: 如果两个函数名相同,一个无变量,一个有一个缺省参数会怎么样?
在这里插入图片描述
生成解决方案:
在这里插入图片描述
别担心,对于逻辑有冲突的调用,编译器不会让你过的

2. 引用

2.1引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。在很多场景,可以取代指针的作用。

语法:

//类型& 引用变量名(对象名) = 引用实体

int a = 10;
int& ra = a;//<====定义引用类型
printf("%p\n", &a);
printf("%p\n", &ra);

在这里插入图片描述
可以看到 ra 和 a的地址都相同

**引用类型必须和引用实体是同种类型的, 即 ra 和 a 的类型必须相同**

2.2 引用特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体
//代码示例
int a = 10;
int b = 10;
// int& ra;  该条语句编译时会出错
int& ra = a;
int& rra = a;

printf("%p %p %p\n", &a, &ra, &rra);

在这里插入图片描述

2.3 常引用

  1. const修饰的变量,不能起被没有const修饰的别名,这一行为称为权限放大,通常不被允许。
  2. 没有const修饰的变量,可以起被const修饰的别名,这一行为称为权限缩小,通常被允许。
//代码示例
//允许权限缩小
int a = 10;
const int& new_a = a;
//不允许权限放大
const int b = 10;
printf("%d %d",a,new_a);

在这里插入图片描述

2.4 使用场景

  1. 做参数
//因为是别名, 别名就是传参的变量,就可以实现修改,注意传参必须是传变量,不能传值
void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}
  1. 做返回值
int& Count()
{
	static int n = 0;
	n++;
	// ...
	return n;
}

2.5 引用和指针的区别

在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。在底层实现上实际是有空间的,因为引用是按照指针方式来实现的

//示例代码 :在底层实现上实际是有空间的,因为引用是按照指针方式来实现的
int a = 10;
int& ra = a;
ra = 20;
int* pa = &a;
*pa = 20;

看看反汇编:
在这里插入图片描述
可以看到在汇编代码层面,二者的指令一致。


指针和引用的不同点:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址别名没有自己的地址,指针有自己的地址。
  2. 引用在定义时必须初始化指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  4. 没有NULL引用,但有NULL指针
// 但不能说绝对 此时pi确实给p起了别名一般不这样用
int* p = NULL;
int*& pi = p;
return 0;

在这里插入图片描述
5. 在sizeof中含义不同:引用结果为引用类型的大小但指针始终是地址空间所占字节个数(32位平台下占4个字节)

//示例代码
 int x = 10;
 int& ref = x; // 引用类型
 int* ptr = &x; // 指针类型

 cout << "Size of reference: " << sizeof(ref) << " bytes" << endl;
 cout << "Size of pointer: " << sizeof(ptr) << " bytes" << endl;

在这里插入图片描述
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全

  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值