前言
上篇文章我们介绍了C++基础知识中的命名空间、输入输出语句和缺省参数,
今天,我们就来学习函数重载与引用
函数重载
定义
在编写代码时,当出现多个函数名相同的函数时,C++提供了一种方式,函数重载,使得当人们想使用哪个函数时,就调用哪个函数
它允许我们在同一个作用域内声明多个同名函数,但这些函数的参数类型或参数个数不同或参数顺序不同。
通过函数重载,我们可以用相同的函数名来表示不同的操作,从而提高代码的灵活性和可读性。
类型介绍
下面给出一些例子:
函数参数个数不同
int add(int a, int b, int c) { return a + b + c; } int add(int a, int b) { return a + b; }
函数参数类型不同
int add(int a, int b, int c) { return a + b + c; } int add(int a, double b, int c) { return a + b + c; }
函数参数顺序不同
int add(int b, double a, int c) { return a + b + c; } int add(double a, int b, int c) { return a + b + c; }
注意:
我们并不考虑函数的返回类型是否不同
原因在后面会解释
重载规则
名称修饰
虽然看起来,上面那些函数的名称是一样的,但在编译过程中,编译器会根据这个函数的函数名和它的参数列表编码形成一个唯一的字符串,来表示这个函数。
这样,相同的函数名在编译后会变得不同,因此可以区分函数重载。
参数匹配
在编译时,编译器会根据传入的参数个数和类型来寻找合适的函数
函数调用解析
一旦编译器匹配到合适的函数声明,它就会生成对应的函数调用。
由于名称修饰的作用,函数的实际调用名可能与源代码中的函数名不完全相同。
注意
名称修饰的具体方式和规则在不同的编译器中可能有所不同,这也导致了不同编译器对函数重载的处理方式可能略有差异。
为了保持向后兼容性,C++提供了extern "C"的机制,用于在C++代码中声明使用C语言的函数名称修饰方式。
导入
在学习C++一段时间之后,相信大家都接触到了引用,我们会发现,它和指针很像,这里就做一个对比
指针
我们都知道,指针实际上指的是指针变量,只不过我们口头说成指针而已,
指针就是地址,指针变量存放的就是一个地址
下面给出几个简单的应用示例
int *p = NULL; int a = 0; int *pa = &a;
注意点
多提一句,对于野指针,也就是指向未知空间的指针变量,对它进行解引用操作是非法的
更详细的介绍,可以看我的另一篇文章
引用
下面,我们就来学习什么是引用
定义
引用不是新创建一个变量,而是对于已经存在的变量进行重命名,
编译器不会再单独为引用开辟一块空间,而是将引用和它所引用的变量存储到同一块空间里
格式
类型 &引用名 = 要引用的变量名;
下面给出一个例子
int a = 0; int& b = a;
提示:
上面代码中的a和b是同一个变量,改变a就是改变b、改变b就是改变a
注意:
引用和被引用的变量的类型要相同
引用的特性
1.引用为变量提供了一个别名。通过引用,我们可以使用不同的名称来访问同一个变量。
2.C++要求引用在声明时必须进行初始化,并且一旦初始化后就不能再改变其引用的对象。
3.引用本身并不占用内存空间,它只是变量的一个别名。所以无法对引用获取地址。
4. 引用在函数参数传递中特别有用,它可以通过引用来传递参数,以实现函数内部对参数的修改对原始变量的影响。
引用和指针的区别
1.初始化和重新绑定:引用在声明时必须进行初始化,并且一旦初始化后就不能重新绑定到其他变量。而指针可以不进行初始化,并且可以重新指向其他变量。
2.空引用:C++不允许创建空引用,即引用必须绑定到一个已经存在的对象。但是,指针可以指向空(nullptr)。
3.语法:引用使用&符号进行声明,指针使用*符号进行声明。
4.内存占用:引用本身不占用额外的内存空间,而指针需要存储目标对象的地址,占用一定的内存空间。
常引用
常引用(const reference)是引用的一种特殊类型,在C++中用于限制通过引用访问的对象的修改。
通过将引用声明为常引用,我们告诉编译器,引用所指向的对象是只读的,不允许通过引用对对象进行修改。
常引用通过在引用声明中添加const关键字来实现,其声明形式为:
const T& ref = 引用实体; //T是要引用的对象类型
特点
只读访问:通过常引用,我们只能读取所引用对象的值,不能修改它。任何试图通过常引用修改对象的操作都会导致编译错误。
初始化要求:常引用必须在声明时进行初始化,且只能引用一个同类型的变量或常量。
临时对象:常引用可以绑定到临时对象(右值),但由于临时对象在表达式结束后会被销毁,因此只能访问临时对象的值,不能修改。
应用
1.函数参数传递:通过引用传递参数,可以实现函数内部对原始变量的修改。简化使用指针。
void increment(int& x) { x++; }
int num = 10; increment(num); // 现在num的值为11
2.返回值:函数可以通过引用返回结果,避免创建临时变量。
int& findLargest(int& a, int& b) { return (a > b) ? a : b; } int a = 10, b = 15; int& largest = findLargest(a, b); largest = 20; // 现在b的值为20,即largest为b的引用
3.避免复制:引用可以避免对象的复制,提高代码的执行效率。
void processLargeObject(const LargeObject& obj) { // 处理大对象的操作,不需要复制对象 }
此处使用了常引用,代表在函数内不会对对象进行修改。
注意
在第二点做返回值时,要注意不能将临时变量引用返回
int& fun()
{
int a = 10;
return a;
}
例如此代码,变量a在函数执行结束之后便会被立刻销毁,若此时仍然根据引用去当作别名使用,对导致结果的不确定性,是不合法的操作。
内联函数
对于内联函数的介绍,可以看我之前的一篇文章
结语
关于函数重载、引用和内联函数的学习和介绍到这里就结束了,希望能对你有帮助。我们下次见~