1

我遗漏了一些东西,或者 const-correctness 与指针(或者可能是智能指针,因为这是我测试过的?)的预期效果不太一样。无论如何,这是我在尝试 PIMPL 习语的变体时观察到的。

我声明了以下内容:

class A {
public:
  A(...);
  ...
  bool update_stuff(...) const;
  ...
protected:
  bool update_stuff_impl(...) const;
  ...
private:
  struct pimpl;
  pimpl* m_pimpl;
};

对于实施,我有类似的东西:

struct A::pimpl {
  pimpl(...): some_data(new some_type());
  ...
  some_method1(...); // Modifies content of some_data
  some_method2(...); // Modifies content of some_data 
  ...

  boost::shared_ptr<some_type> some_data;
};

A::A(...): m_pimpl(new pimpl(...)) {
  ...
}

bool A::update_stuff(...) const {
   if( !update_stuff_impl(...) ) {
      return false;
   }
   return true;
}

bool A::update_stuff_impl(...) const {
   //-Change content of pimpl::some_data here
   m_pimpl->some_method1(...);
   m_pimpl->some_method2(...);
   return true;
}

我难以理解的是如何摆脱const对函数使用限定符A::update_stuff(...)以及A::update_stuff_impl(...)何时实际修改A::pimpl::some_data??!或者这是预期的行为还是只是简单的错误使用?如果是后者之一,如果您能确定如何纠正它,请欣赏?

感谢您的时间和兴趣。

4

2 回答 2

2

C++ 保护pimpl* m_pimpl变量的常量。它不允许更改指针的值。但是它允许对这个指针指向的对象做任何事情。一般没有办法保护它。

例如,考虑一个类成员变量int a; int* b;。在类成员函数中,我们可以执行以下操作:

int a_copy = a;
a_copy = 42;
int* b_copy = b;
*b_copy = 42;

这里a_copyb_copy是局部变量。它们不受您所在对象的 const 保护。因此可以使用 const 方法执行此代码。不同的是a这里的变量值没有改变,而*b值已经改变了。由于可以轻松复制指针,因此编译器无法知道某个指针是否等于位于 const 对象成员值中的任何指针。

于 2013-06-09T07:30:56.980 回答
2

这不是一个新发现,您可以阅读 C++ 中的“const is shallow”之类的内容。是什么导致了物理常量和逻辑常量之间的自然区别(在第二个之后阅读)。

如果您在课堂上有指针,无论是聪明的还是愚蠢的,您都可能涉及到这个问题并且必须仔细设计。考虑到没有发现修改指针另一端的附加数据。

可能的解决方法是使指针 const T* 并添加返回 T* 的私有成员函数。另一个是限制对指针的直接访问,并且需要一对函数,一个是常量,另一个是非常量。

于 2013-06-09T10:29:09.080 回答