I had an idea for a feature for C++, and I was wondering if it was possible to create.
Let's say I want a private variable in 'MyClass' to be accessible only by two functions, the public getter and setter. That is, if another public or private function of MyClass tries to get or change the value of my super-private variable, I will get a compile error. However, the getter and setter behave normally.
Any ideas?
Edit 1: A use case is having the getter/setter perform error checking or other form of logic. I wouldn't want even the class itself touching the variable directly.
Edit 2:
Something like this then:
template <class T>
class State{
private:
T state;
public:
State()
{
state = 0;
}
T getState()
{
return state;
}
void setState(T state)
{
this->state = state;
}
};
And then any class can inherit it and access 'state' only through the getter/setter. Of course, the class is useless without modifying the getter and setter according to your desired logic.
The granularity of accessibility in C++ is the class.
So if you need to make a variable accessible to only two methods you need to move the variable and the two methods into a separate class, dedicated to maintaining privacy..
You could wrap the variable in a class and make it private there and a const T&
getter. Than you declare the get and set member functions of the containing class as friends to that wrapper. Now you keep the wrapper class as a member in your original class. That should achieve what you want albeit it looks hard to maintain and not very useful.
So here is some dummy implementation that shows how this would work (Note that the whole new VeryPrivateWrapper
business is just a wacky way around declarations, a unique_ptr
would be more helpful):
class VeryPrivateWrapper;
class Original {
VeryPrivateWrapper* m_wrapper;
public:
Original();
// imagine that I remembered the rule of three here
void set(int);
void other();
};
// make this a template for more fun
class VeryPrivateWrapper {
int m;
public:
const int& get() const { return m; }
// !!!
// the important bit
// !!!
friend void Original::set(int);
};
Original::Original() : m_wrapper(new VeryPrivateWrapper) {}
void Original::set(int i) {
m_wrapper->m = i;
}
void Original::other() {
// this borks as we would like
// m_wrapper->m = 23;
}
int main()
{
Original o;
o.set(3);
return 0;
}
I believe this is what you asked for. Is it desirable? Some people will think this is an abomination.
If you decided to use it, you'll probably want to pull out the public Get and Set from the macro and write those manually.
#define SUPER_PRIVATE(c,t,m) \
template <typename C, typename T> \
class SuperPrivate##m { \
friend T& C::Get##m(); \
friend void C::Set##m(const T&); \
T value; \
}; \
public: \
t& Get##m() { return m.value; } \
void Set##m(const t& value) { m.value = value; } \
private: \
SuperPrivate##m<c,t> m;
class SomeClass
{
public:
SomeClass()
{
SetX(42);
SetY(58);
}
int DosomethingWithX() { return GetX() * 2; }
// int DosomethingWithX2() { return X.value * 2; } // error
// int DosomethingWithX3() { return X; } // error
SUPER_PRIVATE(SomeClass, int, X);
SUPER_PRIVATE(SomeClass, int, Y);
};
int main()
{
SomeClass someObject;
int x1 = someObject.GetX();
int y1 = someObject.GetY();
someObject.SetY(89);
int y2 = someObject.GetY();
int x2 = someObject.DosomethingWithX();
}
I would put a very ugly name to the variable, and a nice one to the getter/setter:
class Foo
{
private:
int _hey_do_not_use_me_im_super_private_whatever;
public:
int get_whatever() const
{
//extra logic
return _hey_do_not_use_me_im_super_private_whatever;
}
void set_whatever(int we)
{
//extra logic
_hey_do_not_use_me_im_super_private_whatever = we;
}
};
A comment expaining what super-private means will be most welcome by the people that inherits your code.