PIMPL 类的 setter 应该是 const 成员函数吗?

JB

我经常使用“指向私有实现的指针”类。这些类的 setter 方法在技术上可以是 const 成员函数,例如:

class MyPrivateClass
{
public:
  int something = 1;
};

class MyClass
{
public:

  // TODO: initialize pointer in constructor
  // TODO: delete pointer in destructor

  // Note how this setter is const!
  void setSomething(int something) const
    {
      p->something = something;
    }

private:
  MyPrivateClass* p;
};

int main()
{
  return 0;
}

这是可能的,因为编译器只强制按位常量,而不是逻辑常量,所以上面的代码应该编译得很好。

我认为这些setter方法应该为const成员函数,让来电者知道对象实际上是被修改(修改逻辑,而不是按位体改,由于指针实现)。

我的问题是:

是否有充分的理由使这些 setter 方法成为 const 成员函数?

Effective C++ 建议(在第 3 项中)尽可能始终使用 const,但我认为这不适用于我的示例。

杰夫加勒特

const尽可能使用”过于简单。这是一个很好的起点,但不是绝对的规则。

在 pimpl 成语中,正如您所指出的,应用规则为我们提供了constsetter。但一个强烈的反驳是,这打破了封装。您的界面现在反映了一个实现选择。想象一下你重构不使用 pimpl。你的类的用户不应该关心这个完全内部的决定,但现在他们关心,因为你必须const从 setter 中删除

在有私有(对用户)但远程(来自类)状态的任何时候都可以进行相同的论证。重构以将该状态带入类将需要在逻辑上不标记非常量成员函数const

如果你能想象一个合理的实现选择,不需要成员函数const,那么不将其标记为const.

propagate_const库基础 TS 中有一个类模板,但它很容易手工编写,它可以帮助您const在 pimpl 成语中使用 -正确性:

#include <experimental/propagate_const>
#include <memory>

template<class  T>
using pimpl = std::experimental::propagate_const<std::unique_ptr<T>>;

struct MyPrivateClass
{
    int something = 1;
};

struct  MyClass
{
    void setSomething(int something) const
    {
        // error: assignment of member 'MyPrivateClass::something' in read-only object
        p->something = something; 
    }

    pimpl<MyPrivateClass> p;
};

另请注意,在另一个答案中,代码示例无法编译:

error: decltype cannot resolve address of overloaded function
             is_const<decltype(&A::x)>::value == \
                                    ^
note: in expansion of macro 'GET'
     void f1()       { GET(f1).f1(); } // OK

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章