函数重载中的const

本文探讨了C++中函数重载与const形参的关系,指出拥有顶层const的形参无法与非const形参区分,除非涉及指针或引用。作者通过四个不同情况分析了const在指针和引用作为形参时如何影响函数重载,强调理解应从函数调用者的角度出发。总结了在指针和引用情况下,const的影响,帮助理解何时形成有效的函数重载。

《C++ Primer(第5版)》Page208 重载和const形参 一节中有一下说明及代码:

一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开来:

1.
Record lookup(Phone);
Record lookup(const Phone);   //重复声明了Record lookup(Phone)

2.
Record lookup(Phone *);
Record lookup(Phone *const);  //重复声明了Record lookup(Phone *)

如果形参是某种类型的指针或引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时的const是底层的:

3.
Record lookup(Account &);        //函数作用于Account的引用
Record lookup(const Account &);  //新函数,作用于常量引用
4.
Record lookup(Account *);        //新函数,作用于指向Account的指针
Record lookup(const Account *);  //新函数,作用于指向常量的指针

个人理解:

函数重载时形参加上const是否是重载,应该站在函数调用着的角度来看:

1. 情况1下,常量:

      实参传入形参Phone后,调用者不管函数内部如何处理形参,因为函数返回时,实参的值不会有任何变化;

      实参传入形参const Phone后,函数不允许修改形参的值,函数返回时,实参的值也不会有任何变化;

      所以对于调用者来说,形参Phone和形参const Phone,没有任何区别,不属于重载。

2. 情况2下,指针常量:

      形参Phone *拷贝实参指针的值(地址),函数并内部可能修改地址的值,但函数返回时,实参指针的值不会有任何变化;但指针地址存储的内容可以改变;

      Phone *const表示形参指针的值即地址是常量不可修改,但指针地址存储的内容可以改变;

      所以对于调用者来说,形参Phone *和形参Phone *const,是一样的效果,不属于重载。

3. 情况3下,引用:

      形参Account &是实参的别名,函数内部可以修改其值,且函数返回时,实参值也会随之变化;

      const Account &表示形参是实参的别名,但是不能修改其值,所以在函数返回时,实参值不可能发生改变;

      所以对于调用者来说,形参Account &和形参const Account &,得到的结果可能不一样,属于函数重载。

4. 情况4下,常量指针:

      形参Account *拷贝实参指针的值(地址),函数并内部可能修改地址的值,但函数返回时,实参指针的值不会有任何变化;但指针地址存储的内容可以改变;

      const Account *表示形参指针地址存储的内容不可改变,虽然指针的值可变,但函数返回时,实参指针的值不会有任何变化;

      所以对于调用者来说,形参Account *和形参const Account *,得到的结果可能不一样,属于函数重载。

这样理解的话,就可以不用记忆什么顶层底层const,纯靠记忆还容易记反。

在 Free Pascal 函数重载中,`const` 是一个重要的修饰符,主要用于表示传递给函数参数是常量,在函数内部不能对其进行修改。以下是关于 `const` 的使用和原理的详细介绍: ### `const` 的使用 #### 1. 基本使用 当在函数参数前加上 `const` 关键字时,表明该参数是一个常量引用。这意味着函数内部不能修改这个参数的值。例如: ```pascal {$mode objfpc}{$H+} uses SysUtils; // 重载函数,使用 const 参数 procedure PrintValue(const AValue: Integer); begin WriteLn('The value is: ', AValue); // 以下代码会编译错误,因为 AValue 是 const // AValue := AValue + 1; end; procedure PrintValue(const AValue: string); begin WriteLn('The string is: ', AValue); end; var Num: Integer; Str: string; begin Num := 10; Str := 'Hello'; PrintValue(Num); PrintValue(Str); end. ``` 在上述代码中,`PrintValue` 函数重载了两次,分别接受 `Integer` 和 `string` 类型的 `const` 参数。在函数内部尝试修改 `const` 参数会导致编译错误。 #### 2. 性能优化 使用 `const` 参数可以提高性能,特别是对于大型数据结构(如字符串、数组、对象等)。因为传递 `const` 参数时,不会进行数据的复制,而是传递数据的引用。例如: ```pascal {$mode objfpc}{$H+} uses SysUtils; // 处理大型字符串的函数,使用 const 参数 procedure ProcessLargeString(const LargeStr: string); begin // 处理 LargeStr WriteLn('Processing large string: ', Copy(LargeStr, 1, 10)); end; var BigString: string; begin BigString := StringOfChar('A', 10000); ProcessLargeString(BigString); end. ``` 在这个例子中,`ProcessLargeString` 函数接受一个 `const` 字符串参数。由于传递的是引用,而不是复制整个字符串,因此避免了不必要的内存开销。 ### `const` 的原理 在 Free Pascal 中,`const` 参数的原理基于编译器的实现。当函数接受一个 `const` 参数时,编译器会确保在函数内部不会修改该参数的值。从技术上讲,`const` 参数通常以引用的方式传递(对于大型数据结构),这意味着函数接收到的是数据的内存地址,而不是数据的副本。 对于基本数据类型(如 `Integer`、`Char` 等),`const` 参数可能会以值传递的方式处理,但编译器仍然会强制执行常量性,即不允许在函数内部修改参数的值。 ### 总结 - `const` 参数用于表示传递给函数参数是常量,在函数内部不能修改。 - 使用 `const` 参数可以提高性能,特别是对于大型数据结构。 - 编译器会强制执行 `const` 参数的常量性,确保函数内部不会修改参数的值。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值