8

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

代码解释:

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 之类的东西?

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

4

7 回答 7

2

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

#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),但对于这些情况无能为力。

于 2012-12-13T19:31:17.623 回答
1
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但尝试修改对象状态的函数根本不会编译。

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

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

于 2012-12-13T19:03:08.637 回答
1

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

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
};
于 2012-12-13T19:15:17.480 回答
1

成为xprivate成员subClass,并成为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 ;
};

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

于 2012-12-13T19:56:55.360 回答
0

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

于 2012-12-13T18:56:25.077 回答
0

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

于 2012-12-13T19:15:42.340 回答
0

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

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

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

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

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

于 2012-12-13T19:16:19.340 回答