C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++缺省参数、函数重载

C++缺省参数、函数重载与引用深入解析

作者:大耳朵土土垚

缺省参数函数重载以及引用的出现是为了补充C语言语法的不足以及对C语言设计不合理的地方进行优化,引用的出现大大降低了我们学习C语言时相对于指针的难度,也便于我们更好的理解和使用,感兴趣的朋友一起看看吧

前言

1. 缺省参数

1.1 缺省参数概念

缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

#include<iostream>
using namespace std;//使用using namespace 命名空间名称引入C++标准
void Func(int a = 0)
 {
 	cout<<a<<endl;
 }
 int main()
 {
	Func();     // 没有传参时,使用参数的默认值 
	Func(10);   // 传参时,使用指定的实参
	return 0;
 }

结果如下:

可以看到在定义void Func(int a = 0)时给int a 参数赋值为0;
所以当使用该函数时,如果不传参数:Func(); 就默认传的参数为之前定义时赋值的0;
如果传参数:Func(10); 就正常传参即可;

注意:

缺省参数不能在函数声明和定义中同时出现(写在声明中):

1.2 缺省参数分类

全缺省参数

void Func(int a = 10, int b = 20, int c = 30)
 {
 cout<<"a = "<<a<<endl;
 cout<<"b = "<<b<<endl;
 cout<<"c = "<<c<<endl;
 }

全缺省参数就是指定义函数时将所有的参数都赋值

半缺省参数

void Func(int a, int b = 10, int c = 20)
 {
 cout<<"a = "<<a<<endl;
 cout<<"b = "<<b<<endl;
 cout<<"c = "<<c<<endl;
 }

半缺省参数就是指定义函数时将部分的参数赋值;
注意:半缺省参数必须从右往左依次连续来给出,中间不能有间隔;

2.函数重载

2.1函数重载概念

例如:

#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;
}

结果如下:

可以看到虽然函数名相同,但是对应不同的参数会调用不同的函数

这里注意,相同类型的参数顺序调换不构成函数重载:

int Add(int left, int right)
{
    cout << "int Add(int left, int right)" << endl;
    return left + right;
}
int Add(int right, int left)
{
    cout << "int Add(int left, int right)" << endl;
    return left + right;
}

结果如下:

当然如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。

2.2函数重载原因

C语言不支持函数重载的主要原因是它的编译器在进行函数调用时是根据函数名来确定具体调用的函数的,在编译阶段就已经决定了函数的调用方式。而函数重载是指多个函数拥有相同的名称但具有不同的参数列表,编译器无法根据函数名来确定具体调用的函数。因此,C语言无法实现函数重载功能。

而C++是通过函数修饰规则来区分同名的函数,只要参数不同,修饰出来的名字就不一样,就支持了重载。

3.引用

3.1引用概念

在C++中,我们可以通过以下方式定义一个引用:

type &ref = variable;//类型&  引用变量名(对象名) = 被引用实体

例如:

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

注意:引用类型必须和引用实体是同种类型的

再举个例子:

可以看到它们都是同一个地址,指向同一个变量

#include <iostream>
int main() {
    int num = 10;
    int &ref = num; // 引用num变量
    std::cout << "num: " << num << std::endl;
    std::cout << "ref: " << ref << std::endl;
    num = 20;
    std::cout << "num: " << num << std::endl;
    std::cout << "ref: " << ref << std::endl;
    ref = 30;
    std::cout << "num: " << num << std::endl;
    std::cout << "ref: " << ref << std::endl;
    return 0;
}

结果如下:

num: 10
ref: 10
num: 20
ref: 20
num: 30
ref: 30

可以看到,无论我们通过num还是ref来修改变量的值,都会影响到另一个变量的值,因为它们实际上是同一个变量的不同名称。

3.2引用特性

void TestRef()
 {
	int a = 10;
    // int& ra;   // 该条语句编译时会出错
	int& ra = a;
	int& rra = a;
	printf("%p  %p  %p\n", &a, &ra, &rra);  
}

结果如下:

3.2常引用

C++中的常引用有两种情况:

const引用:使用const关键字来修饰引用,表示引用的值不可修改。例如:

int x = 10;
const int& ref = x;

在上面的例子中,ref是一个对x的常引用,意味着不能通过ref来修改x的值。

常对象的引用:当引用一个常对象时,引用也必须是常引用。例如:

const int x = 10;
const int& ref = x;

在上面的例子中,ref是对常对象x的常引用。

常引用的作用是为了在不修改值的情况下使用对象,同时可以避免不必要的复制。常引用经常用于函数参数中,以便避免对实参进行复制。

指针和引用进行赋值和初始化时,权限可以缩小,但是不能放大

例如:

const int x = 10;
int& ref = x;//这是错误的,它放大了权限

在上面的例子中,原本的x被const修饰不能被改变数据,但是ref引用它时没有用const修饰说明可以被改动,放大了权限是不被接受的;这和指针是类似的:const int* p1 = NULL; int* p2 = p1;//这也是错误的

3.3使用场景

做参数

void Swap(int& left, int& right)
 {
 int temp = left;
 left = right;
 right = temp;
 }

结果如下:

可以看到我们没有使用传递变量的指针给函数就改变了实参的数据;

使用引用作为函数参数可以避免复制大量的数据,提高函数的效率。同时,通过引用传递参数可以实现对原始数据的修改,而不需要借助指针来实现。

做返回值

引用作为函数的返回值前提是:返回的值在调用完函数后不会被释放销毁

例如:

int& Count()
 {
 static int n = 0;
 n++;
 return n;
 }

n用static修饰为静态全局变量即使函数调用结束也不会被释放,所以可以用引用作为函数的返回值,这样就不需要再临时拷贝一份,减少了空间的消耗;

那么作为函数的返回值有什么作用呢?
举个例子:

#include<iostream>
#include<assert.h>
#define N 10
using namespace std;
//顺序表
typedef struct AY
{
	int arr[N];
	int size;
}AY;
int& PosAt(AY& ay, int x)
{
	assert(x < N);
	return ay.arr[x];
}
int main()
{
	AY ay;
	for (int i = 0; i < N; i++)
	{
		PosAt(ay, i) = i;//利用引用返回修改对应的值
	}
	for (int i = 0; i < N; i++)//打印
	{
		cout << PosAt(ay, i) << " ";
	}
	cout << endl;
	return 0;
}

结果如下:

从上面的函数我们可以知道引用返回除了可以减少拷贝还可以修改返回的对象;

总结:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

3.4引用和指针的区别

(1)在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间;而指针是保存着变量的地址的,是有独立的空间的;

例如:

int main()
 {
 int a = 10;
 int& ra = a;
 cout<<"&a = "<<&a<<endl;
 cout<<"&ra = "<<&ra<<endl;
 return 0;
 }

结果如下:

通过上述例子我们发现引用和原来的变量的地址是一样的;

(2)在底层实现上实际是有空间的,因为引用是按照指针方式来实现的;

例如:

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int& ra = a;
	ra = 20;
	int* pa = &a;
	*pa = 20;
	return 0;
}

结果如下:

通过上述例子,我们调试查看反汇编,发现引用和指针操作底层逻辑是一样的;

(3)引用和指针的不同:

4.结语

以上就是C++中缺省参数、函数重载以及引用的所有内容啦 ~,缺省参数函数重载以及引用的出现是为了补充C语言语法的不足以及对C语言设计不合理的地方进行优化,引用的出现大大降低了我们学习C语言时相对于指针的难度,也便于我们更好的理解和使用,完结撒花 ~🥳🥳🎉🎉🎉

到此这篇关于C++缺省参数、函数重载与引用的文章就介绍到这了,更多相关C++缺省参数、函数重载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文