Есть ли способ в C ++ для создания «супер приватных» переменных? - PullRequest
26 голосов
/ 28 сентября 2011

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

Допустим, я хочу, чтобы личная переменная в 'MyClass' была доступна только двум функциям,общественный геттер и сеттер.То есть, если другая открытая или закрытая функция 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;
    }
};

И тогда любой класс может наследовать его и получать доступ только к «состоянию»через геттер / сеттер.Конечно, класс бесполезен без изменения метода получения и установки в соответствии с желаемой логикой.

Ответы [ 4 ]

62 голосов
/ 28 сентября 2011

Детализация доступности в C ++ - это класс.

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

30 голосов
/ 28 сентября 2011

Вы можете заключить переменную в класс и сделать ее приватной, а также получить const T&. Затем вы объявляете функции-члены get и set-функции содержащего класса в качестве друзей для этой оболочки. Теперь вы сохраняете класс-оболочку как член в своем первоначальном классе. Это должно достигать того, что вы хотите, хотя это выглядит трудно поддерживать и не очень полезно.

Итак, вот некоторая фиктивная реализация, которая показывает, как это будет работать (обратите внимание, что весь бизнес 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;
}
10 голосов
/ 28 сентября 2011

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

Если вы решили использовать его, вы, вероятно, захотите извлечь из макроса общедоступные инструкции «Получить и установить» и написать их вручную.

#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();

}
5 голосов
/ 28 сентября 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...