Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a variable be locked to prevent changes to it in c++?

I am using a member variable and at some point of the program I want to change it, but i prefer to "lock it" everywhere else to prevent unintended changes.

Code to explain:

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
};

The question is: Can it be achieved in some way? Something like permanent const_cast?

I know I could use constructor initialization list and constant right away, but i need to change my variable later.

like image 362
Petr Avatar asked Dec 13 '12 18:12

Petr


3 Answers

Alright, all the other answers I dislike, so here's my idea: hide the variable.

#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++;
    } 
};

There are still ways to bypass the locking of the variable (such as this->x), but nothing can be done for those situations.

like image 200
Mooing Duck Avatar answered Nov 12 '22 00:11

Mooing Duck


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
};

If you mark a member function const like this, you can't do anything in that member that would modify a member of the object (unless that member is mutable or static -- and static isn't really a member of an object at all).

Note that this won't simply prevent you from calling a function that attempts to do such modification -- rather, a function that's marked const but tries to modify the object state won't compile at all.

I should add, however, that I'm not at all convinced that this is really the best design. Rather the contrary, it sounds to me like your requirements on x and y are sufficiently complex that they would probably make more sense as separate classes that enforce the proper constraints directly (e.g., by providing an overload for operator= that only accepts input under the correct circumstances).

In other words, the use of mutable I've shown above is (I think) the simplest and most direct answer to the question you've asked, but it seems fairly probable that you're not really asking the question you should, and you're more likely to benefit from changing the design -- unfortunately, you haven't told us enough about the "big picture" to suggest what the better design might be.

like image 1
Jerry Coffin Avatar answered Nov 12 '22 00:11

Jerry Coffin


Well, I am not sure it is worth your effort, anyway, just in case this is quiz or sth, try to combine private inheritance with friend:

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
};
like image 1
PiotrNycz Avatar answered Nov 12 '22 00:11

PiotrNycz