Подтвердить что ты не робот

Есть ли способ в С++ создавать "супер частные" переменные?

У меня была идея для функции для С++, и мне было интересно, можно ли ее создать.

Скажем, я хочу, чтобы частная переменная в "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. Конечно, класс бесполезен без изменения геттера и сеттера в соответствии с вашей желаемой логикой.

4b9b3361

Ответ 1

Гранулярность доступности в С++ - это класс.

Итак, если вам нужно сделать переменную доступной только для двух методов, вам нужно переместить переменную и два метода в отдельный класс, предназначенный для поддержания конфиденциальности.

Ответ 2

Вы можете обернуть переменную в класс и сделать ее закрытой и 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;
}

Ответ 3

Я считаю, что это то, о чем вы просили. Желательно? Некоторые люди подумают, что это мерзость.

Если вы решили использовать его, вы, вероятно, захотите вытащить общедоступные 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();

}

Ответ 4

Я бы поместил очень уродливое имя в переменную, и хороший для получателя/сеттера:

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

Комментарий, в котором люди, которые наследуют ваш код, будут более приветствовать, какие супер-частные средства будут приветствоваться.