C++ 中的 Const 函数和接口
我将使用以下(简单)接口作为示例:
struct IObject
{
virtual ~IObject() {}
virtual std::string GetName() const = 0;
virtual void ChangeState() = 0;
};
逻辑规定 GetName
应该是 const
成员函数,而 ChangeState
不应该。
不过,到目前为止我看到的所有代码都不遵循这个逻辑。也就是说,上面示例中的 GetName
不会被标记为 const
成员函数。
这是懒惰/粗心还是有正当理由?我强迫客户在逻辑上需要时实现 const 成员函数的主要缺点是什么?
编辑:感谢大家的回复。我认为这几乎是一致的:懒惰/无知是我所看到的原因。
I'll use the following (trivial) interface as an example:
struct IObject
{
virtual ~IObject() {}
virtual std::string GetName() const = 0;
virtual void ChangeState() = 0;
};
Logic dictates that GetName
should be a const
member function while ChangeState
shouldn't.
All code that I've seen so far doesn't follow this logic, though. That is, GetName
in the example above wouldn't be marked as a const
member function.
Is this laziness/carelessness or is there a legitimate reason for this? What are the major cons of me forcing my clients to implement const
member functions when they are logically called for?
EDIT: Thanks for your responses everyone. I think it's pretty much unanimous: laziness/ignorance is the reason for what I'm seeing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为这是懒惰/粗心。
GetName()
应该对对象的状态没有影响,并且IObject
的契约应该明确地声明这一事实。如果继承类以某种方式被迫使
GetName()
具有(隐藏的!)副作用,它们总是可以将相应的字段声明为mutable
。I think it's laziness/carelessness.
GetName()
should have no effect on the object's state, and the contract ofIObject
should state that fact explicitly.If the inheriting class was somehow forced to make
GetName()
have (hidden!) side effects, they could always declare the corresponding fields asmutable
.前者。 如果您确实没有看到任何代码可以正确执行此操作,请立即找到一份新工作。
它允许编译器在编译时发现常见错误。 (没有什么比在编译时发现错误更好的了。在你的桌面上失败的所有东西,都不会在客户的站点上失败。)
十多年前,在我加入一家新公司并开始侵入他们的一个项目后不久,我发现应该是
const
的方法却不是,从而阻止了我的一些const
正确代码的编译。我考虑过放弃我的const
并继续前进,但我自己无法做到这一点。所以我创建了方法
const
- 只是为了发现它调用了其他方法,这些方法也应该是 const,但实际上都不是。所以我也改变了它们 - 只是为了发现......最后,我花了几天时间浏览了整个项目,左右添加了
const
。同事们嘲笑我 - 直到我向他们展示了编译器因我添加 const 而发现的一些错误。有趣的是,在那之后,一些长期存在的、没有人花时间彻底调查的错误也不再可重现。
The former. If you really haven't seen any code which does this right, get a new job immediately.
It allows the compiler to discover common bugs at compile-time. (Nothing better than errors discovered at compile-time. Everything that fails on your desk, won't fail at the client's site.)
More than ten years ago, shortly after I joined a new company and got to hacking at one of their projects, I found that a method that should have been
const
wasn't, preventing some of myconst
-correct code to compile. I considered just casting myconst
away and get on, but I couldn't myself bring to do this.So I made the method
const
- just to discover that it called other methods, which should have been const, too, but weren't either. So I changed them as well - just to discover...In the end, I spent several days hunting through all of the project, adding
const
left and right.Co-workers laughed at me - until I showed them some of the bugs the compiler had discovered due to me adding
const
. Interestingly, a few long-standing bugs nobody had ever taken the time to thoroughly investigate were not reproducible anymore either, after that.虽然我认为“懒惰”的答案可能适合您的情况,但我只想指出,有时单个
const
关键字的表现力不足以捕获类的可变性细节。考虑一下:
我认为这段代码是合理的:
但同时,我也认为这段代码是合理的:
但是,第二位代码将无法编译,因为
unordered_set
只能给出const
对其内容的引用(实时示例)。这是因为对对象的修改可能会更改其哈希码,从而使其在容器中的位置无效。
因此,实际上,
unordered_set
要求operator==
和const
引用相同的标识概念。但这不是我们在第一个用例中想要的。
问题是我们的代码有两个“对象是否改变了”的概念,从不同的角度来看这两个概念都有道理。
但是您只能应用一个
const
关键字,因此您必须选择一个,而另一种情况就会受到影响。While I think the "laziness" answer is probably right in your case, I do just want to make the point that sometimes a single
const
keyword is not expressive enough to capture the details of mutability of your class.Consider:
I think this code is reasonable:
But at the same time, I think this code is reasonable, too:
However, that second bit of code will not compile, because
unordered_set
can only giveconst
references to its contents (live example).This is because a modification to the object could change its hash code, invalidating its location in the container.
So in effect,
unordered_set
demands thatoperator==
andconst
are referring to the same notion of identity.But that's not what we want in our first use case.
The problem is that our code has two notions of "did the object change", which both make sense from different points of view.
But there is only one
const
keyword you can apply, so you have to pick one, and the other case will suffer.