在接口中使用 const 是否有意义?

发布于 2024-10-09 03:46:04 字数 945 浏览 3 评论 0原文

我有一个执行一些计算的模块,并在计算过程中与其他模块进行通信。由于计算模块不想依赖其他模块,所以它暴露了一个这样的接口(当然这是一个非常简化的版本):

class ICalculationManager
   {
   public:
      double getValue (size_t index) = 0;
      void setValue (size_t index, double value) = 0;
      void notify (const char *message) = 0;
   };

想要使用计算模块的应用程序需要编写自己的接口实现,并且将其提供给计算工具,如下所示:

MyCalculationManager calcMgr;
CalculationTool calcTool (calcMgr);
calcTool.calculate();

我现在想知道将“const”添加到 ICalculationManager 接口的方法中是否有意义。

getValue 方法只获取某些内容而不改变任何内容似乎是合乎逻辑的,因此我可以将此设置为 const。 setValue 可能会更改数据,因此不会是 const。 但对于像通知这样更通用的方法我不能确定。

事实上,对于任何方法,我现在都不能确定该方法确实是作为 const 方法实现的,如果我将接口方法设置为 const,我也会强制所有实现都为 const,这可能是不希望的。

在我看来,只有当您事先知道您的实现是什么以及它是否是 const 时,const 方法才有意义。这是真的吗?

将这种接口的方法设置为 const 没有意义吗?如果它有意义,那么确定该方法是否应该是 const 的好规则是什么,即使我不知道实现是什么?

编辑:将通知参数从“char *”更改为“const char *”,因为这会导致不相关的答案。

I have a module that performs some calculations and during the calculations, communicates with other modules. Since the calculation module does not want to rely on the other modules, it exposes an interface like this (this is a very simplified version of course):

class ICalculationManager
   {
   public:
      double getValue (size_t index) = 0;
      void setValue (size_t index, double value) = 0;
      void notify (const char *message) = 0;
   };

Applications that want to use the calculation module need to write their own implementation of the interface, and feed it to the calculation tool, like this:

MyCalculationManager calcMgr;
CalculationTool calcTool (calcMgr);
calcTool.calculate();

I am wondering now whether it makes sense to add "const" to the methods of the ICalculationManager interface.

It would seem logical that the getValue method only gets something and doesn't change anything, so I could make this const. And setValue probably changes data so that won't be const.
But for a more general method like notify I can't be sure.

In fact, for none of the methods I can now for sure that the method is really implemented as a const method, and if I would make the interface methods const, I am forcing all implementations to be const as well, which is possibly not wanted.

It seems to me that const methods only make sense if you know beforehand what your implementation will be and whether it will be const or not. Is this true?

Doesn't it make sense to make methods of this kind of interface const? And if it makes sense, what are good rules to determine whether the method should be const or not, even if I don't know what the implementation will be?

EDIT: changed the parameter from notify from "char *" to "const char *" since this lead to irrelevant answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

桃扇骨 2024-10-16 03:46:04

当您向客户端宣传调用该函数永远不会更改对象的外部可见状态时,您可以创建一个函数const。您的对象只有一项可以检索的状态,即 getValue。

因此,如果 getValue 可以导致下一个 getValue 返回不同的值,那么当然,将其保留为非常量。如果您想告诉客户端调用 getValue() 永远不会更改下一个 getValue() 返回的值,那么请将其设置为 const。

与notify相同:

double d1 = mgr->getValue(i);
mgr->notify("SNTH");  // I'm cheating.
double d2 = mgr->getValue(i);
assert(d1==d2);

如果这对于所有情况和所有i都适用,那么notify()应该是const。否则不应该。

You make a function const when you are advertising to clients that calling the function will never change the externally visible state of the object. Your object only has one piece of state that can be retrieved, getValue.

So, if getValue can cause the next getValue to return a different value then sure, leave it non-const. If you want to tell clients that calling getValue() will never change the value returned by the next getValue() then make it const.

Same for notify:

double d1 = mgr->getValue(i);
mgr->notify("SNTH");  // I'm cheating.
double d2 = mgr->getValue(i);
assert(d1==d2);

If that should hold true for all cases and all i's then notify() should be const. Otherwise it should not be.

且行且努力 2024-10-16 03:46:04

是的。无论何时何地,只要合理,就应该使用 const。执行计算的方法(这是您的界面所建议的)应该改变它的可观察行为是没有意义的,因为它调用了“notify”。 (就此而言,通知与计算有何关系?)

我将接口成员之一设为 const,您不会强制客户端成为 const --您只需允许他们使用 const ICalculationManager 即可。

我可能会制作 Notify const。如果客户端需要执行一些非常量作为通知的结果,那么Notify不是一个好的方法名称——该名称建议非状态修改转换,例如作为记录,而不是修改。

例如,大多数时候您传递接口时,您会希望使用 pass-by-reference-to-const 来传递接口实现者,但如果方法不是 const >,你不能那样做。

Yes. One should use const whenever and wherever it is sensible to do so. It doesn't make sense that the method for performing a calculation (which is what your interface suggests) should change it's observable behavior because it had "notify" called on it. (And for that matter, how is notification related to calculation at all?)

My making one of the interface members const, you don't force clients to be const -- you merely allow them use of a const ICalculationManager.

I would probably make Notify const. If clients need to do something non-const as a result of a notification, then Notify is not a good method name -- that name suggest non-state-modifying transformations such as logging, not modification.

For instance, most of the time you pass your interface around, you're going to want to use pass-by-reference-to-const to pass the interface implementor, but if the methods aren't const, you cannot do that.

み零 2024-10-16 03:46:04

接口应该指导实现,而不是相反。如果您还没有决定某个方法或参数是否可以是 const,那么您的设计就还没有完成。

使用 const 是一种断言代码允许做什么或不允许做什么的方法。这对于推理一段代码非常有价值。例如,如果您的 notify 参数不是 const,那么它会对消息进行哪些更改?如果需要的话,如何使消息变得更大?

编辑:您似乎知道声明 const 参数的价值,所以让我们在此基础上进行构建。假设您想要一个函数来记录计算的值:

void RecordCalculation(const ICalculationManager *calculation);

您可以在该指针上调用的唯一方法是 const 方法。您可以确定,函数返回后,该对象将保持不变。这就是我对代码进行推理的意思 - 您可以绝对确定该对象不会被更改,因为如果您尝试,编译器将生成错误。

编辑 2:如果您的对象包含一些将被修改以响应逻辑常量操作(例如缓存或缓冲区)的内部状态,请继续并使用 mutable这些成员的关键字。这就是它被发明的目的。

The interface should be guiding the implementation, not the other way around. If you haven't decided if a method or parameter can be const or not, you're not done designing.

Using const is a way of making assertions about what the code is or is not allowed to do. This is extremely valuable in reasoning about a piece of code. If your parameter to notify isn't const for example, what changes would it make to the message? How would it make the message larger if it needed to?

Edit: You appear to know the value of declaring a const parameter, so lets build on that. Suppose you want a function to record the value of a calculation:

void RecordCalculation(const ICalculationManager *calculation);

The only methods you'll be able to call on that pointer are the const methods. You can be sure that after the function returns, the object will be unchanged. This is what I meant by reasoning about the code - you can be absolutely certain the object won't be changed, because the compiler will generate an error if you try.

Edit 2: If your object contains some internal state that will be modified in response to operations that are logically const, such as a cache or buffer, go ahead and use the mutable keyword on those members. That's what it was invented for.

白况 2024-10-16 03:46:04

对我来说,这仅取决于您的接口的合同。

对于 getter 方法,我不明白为什么它应该更改任何数据,如果发生这种情况,也许可变是一个选项。

对于 setter 方法,我同意,而不是 const 那里,因为这肯定会以某种方式改变数据。

因为如果不知道通知对您的系统意味着什么,就很难说它是什么。另外,您是否希望实现修改消息参数?如果现在的话,它也应该是 const 的。

For me it only depends on the contract of your interface.

For a getter method I do not see why it should change any data and if this happens, maybe mutable is an option.

For the setter method I agree, not const there because this will certainly change data somehow.

For the notify is hard to say without knowing what it means for your system. Also, do you expect the message parameter to be modified by the implementation? If now, it should be const too.

月依秋水 2024-10-16 03:46:04

无需阅读整篇文章:是的,当然,如果您想在 const 上下文中使用对象(继承 ICalculationManager),这是有意义的。一般来说,如果不操作私有数据,则应始终使用 const 限定符。

编辑:
就像 Mark Ransom 所说:你需要确切地知道你的界面功能应该如何表现,否则你的设计还没有完成。

Without reading your entire post: Yes of course, it makes sense if you want to use an object (which inherits ICalculationManager) in a const context. Generally, you should always use const qualifier if you don't manipulate private data.

EDIT:
Like Mark Ransom said: You need to know exactly how your interface functions should behave, otherwise your not finished designing.

狂之美人 2024-10-16 03:46:04

我知道我会因此遭到很多反对,但在我看来,C++ 中 const 正确性的用处被过分夸大了。 const 的想法很原始(它只捕获一点概念......更改/不更改)并且成本很高,甚至包括代码重复的必要性。而且它的扩展性也不好(考虑 const_iterators)。

更重要的是,我什至不记得一个案例(甚至一个),常量正确性机制帮助我发现了一个真正的逻辑错误,那就是我试图做一些我不应该做的事情。相反,每次编译器阻止我时,const 声明部分都会出现问题(即我试图做的事情在逻辑上是合法的,但方法或参数在有关 const 性的声明中存在问题)。
在所有情况下,我都记得在哪里遇到与 const 正确性相关的编译器错误,修复方法只是添加一些缺失的 const 关键字或删除一些多余的...如果不使用 const 正确性想法,这些错误就不会出现根本就在那里。

我喜欢 C++,但当然我并不喜欢它的每一点(题外话:当我采访某人时,我经常问的一个问题是“你不喜欢<语言>的哪一部分?”..如果答案是“没有”,那么仅仅意味着我正在交谈的人仍处于粉丝阶段,并且显然没有丰富的真实经验)。

C++ 有很多部分非常好,有些部分在我看来很糟糕(例如流格式),有些部分并不糟糕,但在逻辑上既不美观也不实用。常量正确性的想法在我看来是在这个灰色地带(这不是新手的印象......我在 C++ 中进行了许多行和多年的编码后得出了这个结论)。
可能是我,但显然 const 正确性解决了我的大脑没有的问题......我还有很多其他问题,但不是当我应该更改实例状态和何时不应该更改实例状态时令人困惑的问题。

不幸的是(与流格式化不同)你不能忽略 C++ 中的常量正确性机制,因为它是核心语言的一部分,所以即使我不喜欢它,我也不得不遵守它。

你现在可能会说……好吧,但是问题的答案是什么?只是我不会对那部分语义描述太着迷……它只是一个比特,而且价格很高;如果你不确定并且可以在不声明常量的情况下逃脱,那么就不要这样做。引用或方法的常量性对编译器来说从来没有帮助(请记住,它可以合法地被抛弃),它已被添加到 C++ 中,只是作为对程序员的帮助。然而,我的经验告诉我,(考虑到高成本和低回报)这根本不是真正的帮助。

I know I'm going to get a lot of downvotes for this, but in my opinion the usefulness of const-correctness in C++ is vastly exaggerated. The const idea is primitive (it only captures one bit of concept... change/don't change) and comes with an high cost that even includes necessity of code duplication. Also it doesn't scale well (consider const_iterators).

What's more important I cannot remember even a single case (not even ONE) in which the const-correctness machinery helped me by spotting a true logical error, that is I was trying to do something that I shouldn't do. Instead every single time the compiler stopped me there was a problem in the const declaration part (i.e. what I was trying to do was logically legit, but a method or a parameter had a problem in the declaration about const-ness).
In all cases I can remember where I got a compiler error related to const-correctness the fix was just adding some missing const keywords or removing some that were in excess... without using the const-correctness idea those errors wouldn't have been there at all.

I like C++, but of course I don't love to death every bit of it (digression: when I interview someone a question I often ask is "what is the part you don't like about <language> ?" ... if the answer is "none" then simply means that who I'm talking to is still in the fanboy stage and clearly doesn't have a big real experience).

There are many parts of C++ that are very good, parts that are IMO horrible (stream formatting, for example) and parts that are not horrible but neither logically beautiful nor practically useful. Const-correctness idea is IMO in this gray area (and this is not a newbie impression... I came to this conclusion after many many lines and years of coding in C++).
May be it's me, but apparently const correctness solves a problem that my brain doesn't have ... I've many others problems, but not the one of confusing when I should change an instance state and when I shouldn't.

Unfortunately (differently from stream formatting) you cannot just ignore the const-correctness machinery in C++ because it's part of the core language, so even if I don't like it I'm forced to comply with it anyway.

You may now say... ok, but what's the answer to the question ? It's simply that I wouldn't get too crazy about that part of the semantic description... it's just a single bit and comes with an high price; if you're unsure and you can get away without declaring constness then don't do it. Constness of references or methods is never an help for the compiler (remember that it can be legally casted away) and it has been added to C++ just as an help for programmers. My experience tells me however that (given the high cost and the low return) it's not a real help at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文