【问题标题】:Can a variable be locked to prevent changes to it in c++?可以锁定变量以防止在 C++ 中对其进行更改吗?
【发布时间】:2012-12-01 17:34:12
【问题描述】:

我正在使用一个成员变量,并且在程序的某个时刻我想更改它,但我更喜欢在其他任何地方“锁定”它以防止意外更改。

代码解释:

class myClass {
    int x;  // This should be prevented to being changed most of the time
    int y;  // Regular variable
    myclass() {x = 1;}
    void foo1 () {x++; y++;} // This can change x
    void foo2 () {x--; y--;} // This shouldn't be able to change x
                             // I want it to throw a compile error
};

问题是:能以某种方式实现吗?像永久 const_cast 之类的东西?

我知道我可以立即使用构造函数初始化列表和常量,但我需要稍后更改我的变量。

【问题讨论】:

  • 将其设为私有,并且仅在需要时更改?
  • 你想阻止实现改变x,还是想阻止任何人调用该方法?
  • @Joe:我想在编译时抛出一个错误。
  • void foo2 () const {x--;}
  • 如果你不想这么做,为什么foo2 完全修改x?

标签: c++ variables constants


【解决方案1】:

好吧,我不喜欢所有其他答案,所以这是我的想法:隐藏变量。

#define READONLY(TYPE, VAR) const TYPE& VAR = this->VAR //C++03
#define READONLY(VARIABLE) const auto& VARIABLE = this->VARIABLE //C++11

class myClass {
    int x;  // This should be prevented to being changed most of the time
    int y;  // Regular variable
    myClass() :x(1), y(2) {}
    void foo1 () {// This can change x
        x++; 
        y++;
    } 
    void foo2 () {// This shouldn't be able to change x
        READONLY(x); //in this function, x is read-only
        x++; //error: increment of read-only variable 'x'
        y++;
    } 
};

仍有办法绕过变量的锁定(如this->x),但对这些情况无能为力。

【讨论】:

  • 在我看来,如果你打算这样做,你想要像#define lock(v) const auto &v = this->v 这样的东西,所以在函数中它显示为lock(x); /* ... */。模板可能会让你更干净地做同样的事情。
  • 如果我想阻止仅在一个功能中进行编辑,这是一个很好的解决方案,但我可以阻止它吗?
  • @Petr:即使在理论上也无法一概而论。在问题中,您让 cmets 告诉 us 哪些变量被锁定在哪些函数中。编译器将需要相同的一般信息。很容易让它在 any 函数中不可编辑,但如果它在某些函数中是可编辑的,你必须告诉我们/编译器哪些函数。
  • C++11 版本中的一个错误 - 不是const auto& x,而是const auto& VARIABLE。无论如何 - 很容易打破 - 只需 this->x++...
  • @PiotrNycz:我考虑过,但我现在把它放在答案中。
【解决方案2】:
class myClass {
    int x;
    mutable int y;
public:
    myclass() : x(1) {}
    void foo1 () {x++; y++}      // this can change x or y
    void foo2 () const { y--; }  // this can't change x by can change y
};

如果您像这样标记成员函数const,则不能在该成员中执行任何会修改对象成员的操作(除非该成员是mutablestatic -- 和static根本不是对象的成员)。

请注意,这不会简单地阻止您调用尝试进行此类修改的函数 - 相反,标记为 const 但尝试修改对象状态的函数将根本无法编译。

不过,我应该补充一点,我根本不相信这真的是最好的设计。相反,在我看来,您对xy 的要求已经足够复杂,以至于它们作为直接强制执行适当约束的单独类可能更有意义(例如,通过为operator= 提供重载仅在正确的情况下接受输入)。

换句话说,我在上面显示的mutable 的使用是(我认为)对您提出的问题的最简单和最直接的答案,但是似乎很有可能你并没有真正问你应该问的问题,而且你更有可能从改变设计中受益——不幸的是,你没有告诉我们足够多的“大局”来建议更好的设计可能是什么。

【讨论】:

  • @MooingDuck:谢谢。已更新。
  • mutable?我想我会放弃const 的想法并亲自隐藏变量。或者单元测试什么的。
  • @MooingDuck:这是对他所问问题的最直接答案。我想我应该添加一些警告。
  • 嗯,这是个好主意,但不幸的是,这意味着所有常规变量都必须是可变的,所有常规函数都必须是 const,对吧?而且我觉得这样写也不是什么好主意。
  • @Petr:是的,正如我在回答中所说的,我认为您需要的是不同的设计——但还不足以确定该设计是什么应该是。
【解决方案3】:

好吧,我不确定这是否值得你努力,无论如何,以防万一这是测验或某事,尝试将私有继承与朋友结合起来:

class MyClassX {
protected:
  MyClassX() : x(1) {}
  int x;
public:
  int getX() const { return x; } // read only access
};
class MyClassY {
protected:
  MyClassY() : y(0) {}
  int y;
  friend class MyClass;
public:
  int getY() const { return y; }
};
class MyClassXY : private MyClassX, private MyClassY {
public:
    void foo1 () {x++; y++}      // this can change x or y
};
MyClass : public MyClassXY {
public:
    void foo2 () const { y--; }  // this can't change x but can change y
};

【讨论】:

  • 不是测试,只是我的好奇心。
  • @Petr - 我没有尝试我的解决方案,如果需要修复,请告诉我。据我所知,它应该满足您的限制。
  • @Petr (+1) 出于好奇,我始终相信这是件好事。
【解决方案4】:

使x 成为subClass 的成员private,并使foo1 成为subClass 的朋友功能。像这样:

class myClass {
    int y;  // Regular variable
    myClass() : x (1) {}
    void foo1 () {x.x++; y++;} // This can change x
    void foo2 () {x.x--; y--;} // This shouldn't be able to change x
                            // I want it to throw a compile error
    class subClass {
      friend void myClass::foo1() ; // This must come after the declaration of foo1
      int x ; // private
    public:
      subClass (int x) : x (x) { }
      int read_x() const { return x ; }
      } x ;
};

这会在您想要的地方引发编译器错误。

【讨论】:

  • 我很困惑,因为你从不使用read_x,但你是对的:ideone.com/JTkfSq
  • @Mooing Duck:只写变量有什么用?
【解决方案5】:

你不能做你想做的事...... 如果我错了,请有人纠正我。

【讨论】:

  • 他希望 foo1 更改 x,但不希望 foo2
  • @benjarobin:变量可以通过隐藏来锁定
  • @Mooing Duck:但是如果我把它隐藏起来(不管那是什么意思),我可以将它用于其他地方的只读目的吗?
  • @Petr:是的,如果它只隐藏在一个函数中。
【解决方案6】:

从技术上讲,答案是否定的,只要类可以看到变量并且它不是常量 - 它可以修改它。 但是你可以通过将你想要锁定的变量解耦到一个单独的类中来完成你想要的。

【讨论】:

    【解决方案7】:

    创建一个带有私有 x 变量的类。在里面写下你的方法。

    从这个类派生出你的实际类。让 x 持有者成为实际班级的朋友。

    X 持有者在 x 持有者中使用类似 CRTP 的强制转换(静态转换为基类)将其转换为指向您的实际类的指针。

    从你的 x 持有者中暴露一个 x getter。

    我不会打扰自己,但这比滥用 mutable 和 const 更好。

    【讨论】:

      猜你喜欢
      • 2019-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-25
      • 1970-01-01
      • 2011-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多