Search code examples
c++settergetteraccess-specifier

How to make inaccessible class variable


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.


Solution

  • 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.