4

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

struct IObject
{
  virtual ~IObject() {}

  virtual std::string GetName() const = 0;
  virtual void ChangeState() = 0;
};

逻辑规定GetName应该是const成员函数,而不应该是成员函数ChangeState

不过,到目前为止我看到的所有代码都没有遵循这个逻辑。也就是说,GetName在上面的示例中不会被标记为const成员函数。

这是懒惰/粗心还是有正当理由?我强迫我的客户const在逻辑上要求他们实现成员函数的主要缺点是什么?


编辑:感谢大家的回复。我认为这几乎是一致的:懒惰/无知是我所看到的原因。

4

3 回答 3

10

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

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

于 2010-05-19T16:36:43.213 回答
6

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

前者。如果您真的没有看到任何代码可以做到这一点,请立即找到一份新工作

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

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


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

于 2010-05-19T16:36:01.590 回答
0

虽然我认为“懒惰”的答案在您的情况下可能是正确的,但我只想指出,有时单个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您只能应用一个关键字,因此您必须选择一个,而另一种情况将受到影响。

于 2020-03-28T20:40:01.887 回答