'可变'变量只能通过其中一个const方法变量?

时间:2016-12-13 17:49:10

标签: c++

今天我已经了解了C ++中的mutable关键字,并希望在我的代码中使用它。

我有一个包含许多const方法的类,其中一个应该能够修改一些对象的变量(保留对象的逻辑状态)。但是,我不想让所有const方法修改变量,只修改选定的变量。有没有办法做到这一点?也许与const_cast

(我所讨论的代码是Union-Find structure的实现。Find操作不会改变结构的逻辑状态(它只搜索树的根),但是通过执行所谓的路径压缩来改变物理状态)

谢谢!

编辑:我已经添加了我所指代码的摘录:

class UnionFind {
  public:
    void Union(int a, int b) {...}

    int Find(int x) const {
      // logically, this method is const
      while(x != parents[x]) {
        // path compression
        // the next three lines modify parents and sizes, 
        // but the logical state of the object is not changed
        sizes[parents[x]] -= sizes[x];
        sizes[parents[parents[x]]] += sizes[x];
        parents[x] = parents[parents[x]];

        x = parents[x];
      }
      return x;
    }

  int someOtherMethodThatAccessesParents() const {
    // this method does access parents, but read only.
    // I would prefer if parents behaved like if it was 
    // not 'mutable' inside this method
    ...
  }

  private:
    // these have to be mutable if I want the Find method
    // to be marked const (as it should be)
    // but making them mutable then does not enforce 
    // the physical non-mutability in other const methods :(
    mutable std::vector<int> parents;
    mutable std::vector<int> sizes;
 };

2 个答案:

答案 0 :(得分:3)

乍一看,除非你使用令人讨厌的const_cast,否则无法实现。但是不要这样做,因为尝试修改最初声明为const的const_cast之后的变量的行为是未定义的。

然而,使用友谊来实现你想要的东西可能是可行的,因为这可以在功能的基础上进行控制,而正如你所正确指出的那样,可变性是不可能的。

将要修改的变量放在基类中并将其标记为私有。也许提供一个&#34; getter&#34;对该成员的功能。该函数将是const,并且可能会返回对该成员的const引用。然后让你的函数成为该基类的朋友。该函数将能够更改该私有成员的值。

答案 1 :(得分:-4)

如果你有能力使用% ./Select.sh 0 false 0 true 0 null 0 "" 4 ***ERROR*** ,这是正确的方法。

尽管如此,你可以做你想要的事情。通常这是通过“假mutable”成语:

完成的
this

然后通过新指针正常访问您的字段。如果你必须支持一些没有MyClass *mutableThis = const_cast<MyClass*>(this); 支持的旧编译器,这也是这样做的方法。

但请注意,这通常是一种危险的做法,因为它很容易引导您进入未定义行为的可怕领域。如果原始对象实际上是声明 mutable(而不是仅通过const指针/引用访问),那么您就会遇到麻烦。

简而言之:尽可能使用const,当你不能使用假mutable时,但只有当你知道自己在做什么时才使用this