函数重载
当我们需要调用某一种功能时,都需要调用其对应的某一个函数,但是如果要记住如此多的函数名这无疑是一件非常困难的事情,就比如咱们需要在电脑上通过程序画一幅图片一样,我们需要画圆、长方形、正方形、三角形、直线等等,但是如果我们将其以此定义函数一方面名称太多不好记忆,另一方面编写过于杂乱没有条理,因此,我们能不能就使用一个函数,但是依据某种方法,去画出不同的图形?在这里,介绍一种叫做函数重载的使用方法。
函数重载是指函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表,包括参数个数或类型或顺序必须不同,一次来处理功能类似数据类型不同的问题。
函数重载的形式
1. 参数个数不同
void test(int i)
{
cout << i << endl;
}
void test(int i, int j)
{
cout << i << j << endl;
}
2. 参数类型不同
void test(int i)
{
cout << i << endl;
}
void test(char i)
{
cout << i << endl;
3. 参数顺序不同
void test(int i,char j)
{
cout << i << j << endl;
}
void test(char j,int i)
{
cout << j << i << endl;
}
【注意】
倘若形参列表相同,仅仅改变返回值类型,并不能实现重载,因为在底层中,返回值类型不参与函数的命名。
C++之所以支持函数重载功能的原因在于其编译时对函数的命名规则与C语言不同,其一般使用函数作用域加函数名加参数列表等进行组合命名,因此可以定位到相对应功能的函数
引用
概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会未引用变量开辟内存空间,它和它的引用的变量公用同一块内存空间,就好像一个人有他在身份证上的名字,有父母给起的小名,有爱称有绰号,但是终归是一个人。
语法
类型+&+引用变量名=引用实体 引用类型必须和引用实体是同一种类型,修改引用的值就是修改实体的值。
例
#include<iostream>
using namespace std;
int main()
{
int a = 100;//实体a
cout << a << endl;
int& b = a;//引用b作为a的外号
b = 1000;
cout << a << endl;//b改变后,a同时进行改变
cout << b << endl;
return 0;
}
引用的特点
1. 引用在定义时必须初始化(在给别人取小名时,必须对应这个小名指的是哪个人,不然不知道叫谁不是吗)
int main()
{
int a = 100;
int& b;//引用未初始化,会报错
b = a;
cout << a << endl;
cout << b << endl;
return 0;
}
2. 一个变量可以有多个引用(一个人的一生中会扮演多个角色,小名、别名、网名、笔名、绰号、爱称等等,但是这些不同的称呼都是指向同一个人,且对一个进行改变时,意味着本人也正在进行改变)
int main()
{
int a = 100;
cout << a << endl;
int& b=a;
int& c = a;
int& d = a;
d = 10;
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
return 0;
}
3. 引用一旦引用某个实体,再不能引用其他的实体(一群小伙伴在一起玩耍,会起符合各自特点的绰号,一旦确定这个绰号属于谁,那么这个绰号别人就不能用了,不然多尴尬)
int main()
{
int a = 100;
int& b=a;
int c = 10;
&b = c;//这里改变了引用的指向,会报错
cout << a << endl;
cout << b << endl;
return 0;
}
【注意】请注意区分以下两种情况(int& b=a;)
&b=c; //这是改变引用的指向
b=c; //这个是对引用的实体赋值
常引用
常引用指的是引用指向的实体不能修改
语法
const +类型+&+引用变量名=引用实体
int main()
{
const int a = 100;
const int& b=a;
b = 1000;//不能修改会进行报错
cout << a << endl;
cout << b << endl;
return 0;
}
【注意】这里还有一种隐式用法,当不同类型进行引用时,比如:int& a=d;d是一个double型的变量,这样是行不通的,但是变成常引用之后就可以,这是因为在这个过程中会有一个匿名参数来保存d的整数部分,加上const不可修改便可以正确执行。
int main()
{
double d = 20.36;
const int &a = d;
cout << a << endl;
return 0;
}
引用使用场景
1. 做参数
引用在使用时不需要进行拷贝,从而大大节省了程序运行的时间。在作为参数时可以直接用引用的变量名,对其进行修改可以直接作用到实体上。
如 void test(int& a,int& b)
void Swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
2. 做返回值
需注意:如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。即保证返回值的生命周期需要大于函数的生命周期。
int& test(int &a ,int& b )
{
static int n = 0;
n=a+b;
return n;
}
引用与普通传值的比较
在我们以值作为参数或者返回值类型时,需要知道其实传递的本不是该值本身,即在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是会以此创建一个临时变量,将该临时变量的值进行使用,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
【注】
引用的本质是指针但是语法上不能以指针的形式写。
引用与指针的区别
1.引用在定义时必须初始化,指针没有要求
2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型
实体
3. 没有NULL引用,但有NULL指针
4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占
4个字节)
5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
6. 有多级指针,但是没有多级引用
7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
8. 引用比指针使用起来相对更安全