1

I'm wondering if it is possible to make a class variable inaccessible inside this class? The only way to change the value of this variable will be through class setter. For example:

class foo
{
private:
    int m_var;
    bool m_isBig;
    void setVar(int a_var)
    {
        // do something before setting value, like emitting signal
        m_var = a_var;
    }
    void method()
    {
        int copy = m_var; // ok
        m_var = 5; // error!
        setVar(101); // ok
        doSomething();
    }
    void doSomething()
    {
        if(m_var > 5)
        { m_isBig = true; }
        else
        { m_isBig = false; }
    }
};

I know that I could write another class only with setters and getter, but then I will don't have access to other methods/vars from class foo(encapsulation!). I think this could be a common problem, and there could be some design pattern for this, but I can't found any.

EDIT: I edited the code to be clear, what I want to do in setter.

Isaac
  • 115
  • 10
  • possible duplicate of [Can a variable be locked to prevent changes to it in c++?](http://stackoverflow.com/questions/13866440/can-a-variable-be-locked-to-prevent-changes-to-it-in-c) – hlscalon Sep 25 '15 at 20:04
  • You could probably get this functionality as you say by creating another class with only setters and a getter, and then to give that additional class access to methods/vars from foo you would have foo declare it as a `friend`. I expect you can even make this an internal class, possibly only defined in an implementation file if you really want to keep it hidden. – YoungJohn Sep 25 '15 at 20:06
  • why do you want this? If you have a private member you're the responsible of implementation so what's the meaning? – Jepessen Sep 25 '15 at 20:12
  • Your code [doesn't compile](http://ideone.com/ImQwmQ), did you mean [`private:`](http://ideone.com/EmLFMP) actually? – πάντα ῥεῖ Sep 25 '15 at 20:18
  • @πάνταῥεῖ yes, edited. – Isaac Sep 25 '15 at 20:28
  • @Isaac Your function member declarations are still `private` and render useless. – πάντα ῥεῖ Sep 25 '15 at 20:35

3 Answers3

0

You can wrap the integer into a special class, and only define setVar(), but not an assignment operator taking an int

class M_type
{
    int m_var;
public:
    explicit M_type(int m) : m_var{m} {}
    operator int() const { return m_var; }
    void setVar(int a_var) { m_var = a_var; }
};

class foo 
{
    M_type m_var;
    bool m_isBig;
public:
    explicit foo(int m) : m_var{m} {};

    void method()
    {
        int copy = m_var; // OK, calls operator int()
        m_var = 5; // error, no operator=(int)
        m_var.setVar(101); // OK, calls setVar(int)
        doSomething();
    }

    void doSomething()
    {
        if(m_var > 5)
        { m_isBig = true; }
        else
        { m_isBig = false; }
    }    
};

Make sure to give M_type an explicit constructor taking an int, and only an implicit conversion operator int() that acts as a "getter". If you make the constructor implicit as well, the compiler-generated assignment operator=(M_type const&) will be able to convert the argument 5 to an M_type.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
0

You can't do exactly you're asking in C++. All variables in a class are visible to all methods in a class, regardless of whether they are public or private.

The question you want to ask yourself is: why would a class want to hide things from itself? The class's interface is the boundary between the class's internal implementation and the services it provides to the outside world. You're either inside the class or outside.

With this in mind, perhaps you use case is such that writing an additional class is the appropriate thing to do?

alexgolec
  • 26,898
  • 33
  • 107
  • 159
0

I'm not aware of a pattern for this, but one possibility is to wrap the member inside a nested class. I think this is also better style, since the creation of a new type expresses the intent that this member is not just an integer, but, instead, has unique behaviour.

class foo {
    class MVar {
      public:
        MVar(foo* parent, int value = 0) : m_parent(parent), m_value(value) {}
        MVar& operator=(const MVar&) = delete; // disable assignment
        operator int() const { return m_var; }
        void set(int new_value) {
            // do something, possibly with m_parent
            // nested classes have access to the parent's private members
            m_value = new_value;
        }
      private:
        foo* m_parent;
        int m_value;
    } m_var;
    void method() {
        int copy = m_var; // ok
        m_var = 5;        // error
        MVar.set(101);    // ok
    }
};

This doesn't perfectly do what you want, since m_var doesn't really have type int, but it's something to consider.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • why the back pointer? why not a simple value-wrapper around an int? – TemplateRex Sep 25 '15 at 20:15
  • @TemplateRex In case the action the OP wants to take when setting the variable needs to invoke methods on the parent. The OP does say something that might resemble this (but the question isn't entirely clear). – Brian Bi Sep 25 '15 at 20:16
  • it sounds way too complicated, `m_var` is an `int` wrapper, all he wants is set it to some integer value. if `method()` needs other context, then it can get this from the `foo` class, but surely `m_var` has no use for it – TemplateRex Sep 25 '15 at 20:18
  • Is making MVar friend of foo simpler than passing pointer to class foo? – Isaac Sep 25 '15 at 20:24