成员函数什么时候应该有 const 限定符,什么时候不应该有?

2024-04-27

大约六年前,一位名叫 Harri Porten 的软件工程师写道本文 http://www.froglogic.com/~porten/const.html,提出这样的问题:“成员函数什么时候应该有 const 限定符,什么时候不应该有?”我发现这是我能找到的关于这个问题的最好的文章,我最近一直在努力解决这个问题,而且我认为我发现的关于 const 正确性的大多数讨论都没有很好地涵盖这个问题。由于当时还没有像SO这样强大的软件信息共享网站,所以我想在这里重新提出这个问题。


这篇文章似乎涵盖了很多基础知识,但作者仍然对返回指针的函数的 const 和非常量重载有疑问。文章的最后一行是:

许多人可能会回答“这要看情况”。但我想问“这取决于什么?”

绝对准确地说,这取决于 A 对象指针对象的状态在逻辑上是否是 A 对象状态的一部分this object.

举个例子,vector<int>::operator[]返回对 int 的引用。 int 引用数是向量的“一部分”,尽管它实际上不是数据成员。因此,常量重载惯用语适用:更改一个元素,您就更改了向量。

对于不是这样的示例,请考虑shared_ptr。这个有成员函数T * operator->() const;,因为有一个 const 是有逻辑意义的智能指针到一个非常数object。引用对象不是智能指针的一部分:修改它不会更改智能指针。因此,是否可以“重新设置”智能指针以引用不同的对象的问题与引用对象是否为 const 无关。

我认为我无法提供任何完整的指导方针来让您决定受指点在逻辑上是否是对象的一部分。但是,如果修改被指向者会更改任何成员函数的返回值或其他行为this,特别是如果受指点参与operator==,那么它很可能是逻辑上的一部分this object.

我宁愿假设它is部分(并提供重载)。然后,如果出现编译器抱怨我正在尝试修改从 const 对象返回的 A 对象的情况,我会考虑我是否真的应该这样做,如果是这样,请更改设计,以便只有指向 A 的指针从概念上讲,它是对象状态的一部分,而不是 A 本身。这当然需要确保修改 A 不会做任何破坏预期行为的事情this常量对象。

如果您要发布接口,您可能必须提前弄清楚这一点,但实际上,从 const 重载返回到 const 函数返回非 const 指针不太可能破坏客户端代码。不管怎样,当您发布一个接口时,您希望已经使用过它一点,并且可能对对象的状态真正包含的内容有所了解。

顺便说一句,我也尝试犯错误,不提供指针/引用访问器,尤其是可修改的访问器。这确实是一个单独的问题(德墨忒尔定律等),但是您可以替换的次数越多:

A *getA();
const A *getA() const;

with:

A getA() const; // or const A &getA() const; to avoid a copy
void setA(const A &a);

您担心这个问题的次数就越少。当然后者也有其自身的局限性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

成员函数什么时候应该有 const 限定符,什么时候不应该有? 的相关文章

  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • 有没有办法在 xcode 上使用 c++0x ?我想使用 gcc 4.4 或更高版本

    我想使用 gcc 4 4 或更高版本进行 iphone 开发 有人知道怎么做吗 不 你不知道 相信我 你不会 Apple 仍保留 gcc 4 2 1 因为 4 2 2 及更高版本使用 GPLv3 这意味着他们必须放弃对其平台的控制 对于 i
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 检测到堆栈崩溃

    我正在执行我的 a out 文件 执行后 程序运行一段时间 然后退出并显示消息 stack smashing detected a out terminated Backtrace lib tls i686 cmov libc so 6 f
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 计算另一个表达式中的 C# 表达式

    我想在另一个表达式中使用一个表达式 Expression
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • 访问 ascx 文件中的母版页控件

    我有一个母版页文件 其中包含 2 个面板控件中的 2 个菜单 我还使用控件来检查用户是否登录并获取用户类型 根据我想要显示 隐藏面板的类型 控件本身不在母版页中引用 而是通过 CMS 系统动态引用 我想在用户控件中使用findcontrol
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • 如何从 Rx Subscribe 回调异步函数?

    我想回调 Rx 订阅中的异步函数 例如 像那样 public class Consumer private readonly Service service new Service public ReplaySubject
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • ASP.NET MVC 路由:如何从 URL 中省略“索引”

    我有一个名为 StuffController 的控制器 具有无参数索引操作 我希望从表单中的 URL 调用此操作mysite com stuff 我的控制器定义为 public class StuffController BaseContr
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • 如何在 winforms 应用程序的主屏幕显示之前显示欢迎屏幕?

    我想在应用程序启动时加载欢迎屏幕 然后用户单击欢迎屏幕上的按钮 然后关闭欢迎屏幕 最后显示主屏幕 static void Main startup method being called Application EnableVisualSt
  • DataContractSerializer 事件/委托字段问题

    在我的 WPF 应用程序中 我正在使用DataContractSerializer序列化对象 我发现它无法序列化具有事件或委托声明的类型 考虑以下失败的代码 Serializable public abstract class BaseCl
  • 如何使用placement new重新初始化该字段?

    我的课程包含字段 private OrderUpdate curOrderUpdate 我一遍又一遍地使用它 经常需要重新初始化 for int i 0 i lt entries size i auto entry entries i ne

随机推荐