C ++中的Const函数和接口

时间:2010-05-19 16:33:19

标签: c++ interface const-correctness member-functions

我将使用以下(普通)接口作为示例:

struct IObject
{
  virtual ~IObject() {}

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

逻辑规定GetName应该是const成员函数,而ChangeState不应该。{/ p>

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

这种懒惰/粗心大意还是有合理的理由?在逻辑上要求我的客户实施const成员函数时,我的主要缺点是什么?


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

3 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分:5)

  

这种懒惰/粗心大意还是有合理的理由?

前者。 如果您确实没有看到任何正确的代码,立即开始新工作

  

在逻辑上要求我的客户强制实施const成员函数时,我的主要缺点是什么?

它允许编译器在编译时发现常见错误 。 (没有比在编译时发现的错误更好的了。桌面上发生故障的所有内容都不会在客户端站点失败。)


十多年前,在我加入一家新公司并且不得不攻击他们的一个项目后不久,我发现应该const的方法不是,阻止了我的一些{{1} 1}} - 正确的编译代码。我考虑过把我的const扔掉然后继续前进,但是我无法自己做这件事 所以我创建了方法const - 只是为了发现它调用了其他方法,它们也应该是const,但也不是。所以我也改变了它们 - 只是为了发现...
最后,我花了好几天时间搜索整个项目,左右添加const 同事们嘲笑我 - 直到我向他们展示编译器发现的一些错误,因为我添加了const。有趣的是,在此之后,没有人花费时间进行彻底调查的一些长期存在的错误也不再具有可再现性。

答案 2 :(得分:0)

虽然我认为“懒惰”的答案可能对您来说是正确的,但我只是想指出一点,有时单个Future<UserTypeWithUserResponse> fetchusertype() async { var api_instance = new ApiClient(); authToken = "XYZ"; UserTypeWithUserResponse responsevalue; defaultApiClient.getAuthentication<OAuth>('BearerAuth') ..accessToken = authToken; try { new UserTypeApi(defaultApiClient).userTypeGet().then((responsevalue) { return responsevalue; }); } catch (error) { throw Exception('error fetching user'); }; } 关键字的表达能力不足以捕获类的可变性的细节。

考虑:

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对其内容(live example)的引用。 这是因为对对象的修改可能会更改其哈希码,从而使其在容器中的位置无效。

因此实际上,const要求unordered_setoperator==引用相同的身份概念。 但这不是我们第一个用例想要的。

问题在于我们的代码有两个“对象改变了”的概念,这两个观点从不同的角度来看都是有意义的。

但是您只能应用一个const关键字,因此您必须选择一个,而另一种情况会受到影响。