C++ 中的 Const 函数和接口

发布于 2024-09-02 03:44:07 字数 491 浏览 15 评论 0原文

我将使用以下(简单)接口作为示例:

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 技术交流群。

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

发布评论

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

评论(3

她说她爱他 2024-09-09 03:44:07

我认为这是懒惰/粗心。 GetName() 应该对对象的状态没有影响,并且 IObject 的契约应该明确地声明这一事实。

如果继承类以某种方式被迫使 GetName() 具有(隐藏的!)副作用,它们总是可以将相应的字段声明为 mutable

I think it's laziness/carelessness. GetName() should have no effect on the object's state, and the contract of IObject 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 as mutable.

奈何桥上唱咆哮 2024-09-09 03:44:07

这是懒惰/粗心还是有正当理由?

前者。 如果您确实没有看到任何代码可以正确执行此操作,请立即找到一份新工作

我强迫客户在逻辑上调用成员函数时实现 const 成员函数的主要缺点是什么?

它允许编译器在编译时发现常见错误。 (没有什么比在编译时发现错误更好的了。在你的桌面上失败的所有东西,都不会在客户的站点上失败。)


十多年前,在我加入一家新公司并开始侵入他们的一个项目后不久,我发现应该是 const 的方法却不是,从而阻止了我的一些 const 正确代码的编译。我考虑过放弃我的 const 并继续前进,但我自己无法做到这一点。
所以我创建了方法 const - 只是为了发现它调用了其他方法,这些方法也应该是 const,但实际上都不是。所以我也改变了它们 - 只是为了发现......
最后,我花了几天时间浏览了整个项目,左右添加了 const
同事们嘲笑我 - 直到我向他们展示了编译器因我添加 const 而发现的一些错误。有趣的是,在那之后,一些长期存在的、没有人花时间彻底调查的错误也不再可重现。

Is this laziness/carelessness or is there a legitimate reason for this?

The former. If you really haven't seen any code which does this right, get a new job immediately.

What are the major cons of me forcing my clients to implement constmember functions when they are logically called for?

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 my const-correct code to compile. I considered just casting my const 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.

等风来 2024-09-09 03:44:07

虽然我认为“懒惰”的答案可能适合您的情况,但我只想指出,有时单个 const 关键字的表现力不足以捕获类的可变性细节。

考虑一下:

class MyClass {
public:
    bool operator==(const MyClass &other) const {
        return identity == other.identity;
    }

    void setVisible(bool vis) { gfx.setVisible(vis); }
    bool isVisible() const;

    // other methods ...

private:
    string identity;
    GraphicsData gfx;
}

我认为这段代码是合理的:

MyClass item = ...
item.setVisible(true);

// I want to call a function and be sure that the object's
// visibility did not change, so pass a const ref.
const MyClass &constRef = item;
someSafeFunction(constRef);

但同时,我也认为这段代码是合理的:

// Imagine an appropriate std::hash<MyClass> has been
// defined, based on MyClass::identity.
unordered_set<MyClass> set = ...

// Hide some items
for (MyClass &item : set) {
    item.setVisible(false);
}

但是,第二位代码将无法编译,因为 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:

class MyClass {
public:
    bool operator==(const MyClass &other) const {
        return identity == other.identity;
    }

    void setVisible(bool vis) { gfx.setVisible(vis); }
    bool isVisible() const;

    // other methods ...

private:
    string identity;
    GraphicsData gfx;
}

I think this code is reasonable:

MyClass item = ...
item.setVisible(true);

// I want to call a function and be sure that the object's
// visibility did not change, so pass a const ref.
const MyClass &constRef = item;
someSafeFunction(constRef);

But at the same time, I think this code is reasonable, too:

// Imagine an appropriate std::hash<MyClass> has been
// defined, based on MyClass::identity.
unordered_set<MyClass> set = ...

// Hide some items
for (MyClass &item : set) {
    item.setVisible(false);
}

However, that second bit of code will not compile, because unordered_set can only give const 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 that operator== and const 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.

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