Ответ 1
Гранулярность доступности в С++ - это класс.
Итак, если вам нужно сделать переменную доступной только для двух методов, вам нужно переместить переменную и два метода в отдельный класс, предназначенный для поддержания конфиденциальности.
У меня была идея для функции для С++, и мне было интересно, можно ли ее создать.
Скажем, я хочу, чтобы частная переменная в "MyClass" была доступна только с помощью двух функций: public getter и setter. То есть, если другая открытая или закрытая функция MyClass пытается получить или изменить значение моей сверх-частной переменной, я получу ошибку компиляции. Однако геттер и сеттер ведут себя нормально.
Любые идеи?
Редактирование 1: Вариант использования, когда геттер/сеттер выполняет проверку ошибок или другую форму логики. Я бы не хотел, чтобы даже сам класс касался переменной напрямую.
Изменить 2: Что-то вроде этого:
template <class T>
class State{
private:
T state;
public:
State()
{
state = 0;
}
T getState()
{
return state;
}
void setState(T state)
{
this->state = state;
}
};
И тогда любой класс может наследовать его и получить доступ к "состоянию" только через getter/setter. Конечно, класс бесполезен без изменения геттера и сеттера в соответствии с вашей желаемой логикой.
Гранулярность доступности в С++ - это класс.
Итак, если вам нужно сделать переменную доступной только для двух методов, вам нужно переместить переменную и два метода в отдельный класс, предназначенный для поддержания конфиденциальности.
Вы можете обернуть переменную в класс и сделать ее закрытой и const T&
getter. Чем вы объявляете get и задаете функции-члены содержащего класса в качестве друзей этой оболочки. Теперь вы сохраняете класс-оболочку в качестве члена в вашем первоначальном классе. Это должно достичь того, что вы хотите, хотя оно выглядит трудно, и оно не очень полезно.
Итак, вот несколько фиктивных реализаций, которые показывают, как это будет работать (обратите внимание, что весь бизнес new VeryPrivateWrapper
- это просто дурацкий путь вокруг объявлений, unique_ptr
будет более полезен):
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;
}
Я считаю, что это то, о чем вы просили. Желательно? Некоторые люди подумают, что это мерзость.
Если вы решили использовать его, вы, вероятно, захотите вытащить общедоступные Get и Set из макроса и записать их вручную.
#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();
}
Я бы поместил очень уродливое имя в переменную, и хороший для получателя/сеттера:
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;
}
};
Комментарий, в котором люди, которые наследуют ваш код, будут более приветствовать, какие супер-частные средства будут приветствоваться.