详解const重载

省流党:const如果修饰 指针本身,不构成重载;如果修饰 指针的指向 或 引用的实体,则构成重载。
正文如下。
我们知道,函数重载要求形参列表不同。有些场景我们可以一眼看出来是否重载,比如形参数量不同、形参类型明显不同(char和double)。但是,下面这些场景呢?

void func(int n) {}
void func(const int cn) {}
void func(int* pn) {}
void func(int* const cpn) {}
void func(int* pn) {}
void func(const int* pcn) {}
void func(int n) {}
void func(int& rn) {}
void func(int& n) {}
void func(const int& crn) {}

答案是,前两组不构成重载,后三组构成重载。
归根究底,不构成函数重载是因为出现了二义性。对于你的传参,编译器有多个选择,无法确定被调用的函数。
以第一组为例,一个int变量,我传给void func(int n);void func(const int cn);都没毛病。究其根本,是因为此处是传值调用
形参只是实参的一份拷贝,两者除了存储数据一致,没有任何联系。形参列表中的const,是限制形参在func内的行为(只可读不可写),这和实参毫无关系。实参不知道,也无需知道func内要发生什么。_实参的任务就是提供形参拷贝的数据。虽然两者的数据是完全一致的,_但形参接受实参数据时,会忽略实参本身的特性,按照形参列表重新设计自己的特性(只读还是可读可写)。就像是你抄同学的作业,虽然你们的答案一模一样,但你可以做自己的处理,比如把变量名改一下。有可能你会选择直接CV,但这只是因为你懒。你抄作业时是有权限稍作改动,让它看起来和你抄的原版不一样。
第二组也是同理。第二个函数的const修饰的是pointer,意指这个指针本身不可修改。这同样也是限制形参在func内的行为。
其实这里也可以理解为是传值调用,因为形参只是将实参存储的地址拷贝了一份,但两者的行为可以全然不同(一个只读,一个可读可写)。实参只是将它存储的数据传递给了实参。之所以说形参的改变可以作用于实参,是由于pointer存储的数据是地址,所以形参解引用也能找到实参指向的变量(这里不用过于纠结,意会就好)。
对于这两组的情况,也就是**const**修饰变量本身,只要实参形参类型一致,实参就可以为形参提供数。甚至类型不一致,允许发生转换也是可以的。因此,编译器不能做出区分,不构成重载。
与之相对,第三组的const修饰的是pointer指向的int。此时,const限制的是指针指向的内容。两个形参都是可读可写的普通指针,但它们指向的变量一个只读,一个可读可写。实参和形参不再是毫无关联的。形参接受实参提供的数据时,不仅仅进行拷贝,还要保证自己不会对指向的内容做任何改动。就像是你去抄学霸的代码,有些东西可以自主改动,但有些是不能改的。比方说,你不能随便把public改成private,改了就错了。
在这种情况下,无论是给int*const int*,还是给const int*int*,都会出现权限问题。只有对应传参才合法。编译器可以找到唯一的函数,因此构成函数重载。
第五组也是类似的。引用的底层是指针,可以理解为是int * const类型。这也是为什么第四组构成重载。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值