Частные функции set / get - Почему частные и как использовать? - PullRequest
4 голосов
/ 24 августа 2011

Я прочитал много руководств, объясняющих, почему я должен использовать «private», и я всегда отвечаю: «Потому что мы не хотим, чтобы кто-то еще устанавливал это как нечто». Итак, позвольте мне задать следующие вопросы:

Предполагая, что я хочу, чтобы переменная была установлена ​​один раз (возможно, что-то вроде имени персонажа в видеоигре, спросите один раз, затем он установлен, а затем вы просто используете переменную get (edit: function) для остальная часть игры) как мне справиться с этим одним набором? Как бы я справился и с этим?

Каково реальное преимущество использования модификатора частного доступа в этом случае? Если я никогда не предложу пользователю ввести имя снова и никогда не сохраню информацию обратно в class.name, разве данные не должны оставаться безопасными (умеренно, если предположить, что код работает так, как задумано)?

Я надеюсь, что кто-нибудь поможет мне с этим, потому что объяснения, которые я гуглил и видел здесь, не совсем успокоили мои мысли.

Спасибо!

Ответы [ 6 ]

2 голосов
/ 24 августа 2011

Спецификаторы доступа в основном служат для обозначения интерфейса класса, а не для эффективного ограничения доступа программиста или защиты вещей. Они служат для предотвращения случайного взлома.

Если что-то установлено один раз, то вы должны попытаться установить это, когда оно будет создано, и сделать это const.

Если интерфейс не должен быть особенно четким (например, если мало кому нужно его изучать), то не имеет смысла тратить усилия на его разработку. Более того, изменения, которые не имеют большого значения в том, как интерфейс используется , могут быть применены позже. Открытая переменная может быть изменена на метод получения / установки с помощью простого поиска и замены.

Если бы это был опубликованный двоичный интерфейс, то вы бы хотели получить его правильно с первого раза. Но вы просто говорите о внутренностях вашей программы.

И вряд ли кто-то случайно сбросит имя игрока.

1 голос
/ 24 августа 2011

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

Я обычно избегаю сеттеров, если вообще могу управлять им.Вместо этого я предпочитаю предоставить возможность устанавливать переменные-члены через конструктор.Я очень рад предоставить получателей, если они имеют смысл.

class player_character_t {
    std::string name_;
public:
    player_character_t(std::string const& name)
    :   name_ (name)
    {
    }

    std::string const& name() const { return name_; }
};

Это заставляет вас откладывать строительство объекта до тех пор, пока вы не получите всю необходимую вам информацию.Это упрощает логику ваших объектов (т. Е. Они имеют тривиальную диаграмму состояний) и означает, что вам не нужно проверять, установлено ли что-то перед чтением (если объект существует, он установлен правильно).

http://en.wikipedia.org/wiki/State_diagram

Пометка вещей как личных помогает предотвратить несчастные случаи.Поэтому, когда вы делаете ошибку, и «код работает не так, как задумано», компилятор может помочь вам обнаружить его.Аналогично, const может помочь обнаружить неправильное использование объектов.

0 голосов
/ 24 августа 2011

Частные геттеры и сеттеры все имеют смысл, когда в рассматриваемые данные входят несколько переменных, есть дополнительные ограничения, которые вы хотите соблюдать, и эти операции выполняются несколько раз в вашем классе.Или когда вы планируете дальнейшие изменения в модели данных и хотите абстрагировать операции с данными, например, используя std :: vector, но планируете сделать это std :: map или аналогичными случаями.

Для личного примера яиметь реализацию интеллектуального указателя с закрытым методом сброса (T *, int *), который по существу является установщиком для хранимого объекта и его счетчика ссылок.Он обрабатывает проверку достоверности объектов и счетчиков ссылок, увеличивает и уменьшает счетчики ссылок и удаляет объекты и счетчики ссылок.В классе он вызывается восемь раз, поэтому имело смысл поместить его в метод, вместо того, чтобы просто каждый раз перебирать переменные-члены, замедляя программирование, вздутие кода и рискуя ошибками в процессе.

IЯ уверен, что частные получатели также могут иметь смысл, если вы абстрагируете данные из модели и / или вам необходимо реализовать проверку на ошибки, например, выдавая инструкции, если данные имеют значение NULL, а не возвращают NULL.

0 голосов
/ 24 августа 2011

Если переменная «пишите один раз, то навсегда только для чтения», я бы рекомендовал сделать ее const элементом, который инициализируется во время построения.В частной функции 'setter' нет значения, потому что она не будет использоваться.Также вы избегаете людей, использующих функцию setter для установки имени, когда оно никогда не предназначалось для установки.

Например:

class Player
{
  private:
    const std::string m_name;

  public:
    Player(const std::string& name) : m_name(name) {}
 };
0 голосов
/ 24 августа 2011

Не путайте интерфейсы private и public класса.Теоретически это совершенно разные интерфейсы, и это всего лишь конструктивная особенность C ++, заключающаяся в том, что они физически расположены в одном объявлении класса.

Совершенно нормально иметь открытый метод получения / установки, когда свойство объекта должнобыть доступным через общедоступный интерфейс, поэтому не существует правила, такого как «сеттер всегда приватен».

Более подробно об этом читайте в книгах (Подробнее) об исключительных C ++ Херба Саттера.Это абсолютно необходимое чтение для тех, кто хочет понимать C ++ и разбираться в нем.

Если у вас есть сомнения по поводу того, следует ли использовать getter / setters над переменными класса, в Интернете есть множество объяснений, почему getter/ сеттеры лучше.

0 голосов
/ 24 августа 2011

Важна последняя скобка: при условии, что код работает так, как задумано.

На мой взгляд, это похоже на разрешения в системах Linux. Вы знаете пароль пользователя root и можете удалить любой файл, но вы не останетесь в системе как root, поэтому ничего не делаете случайно. Точно так же, когда у вас есть закрытая переменная characterNameString, и кто-то (или вы) позже попытается присвоить ей новое значение, она потерпит неудачу. Этот человек должен будет посмотреть код и отметить, что он помечен как закрытый. Этот человек должен будет спросить себя: «Почему это личное? Должен ли я его изменить? Должен ли я сделать это по-другому?» Если они решат, что хотят, то могут. Но это предотвращает глупые ошибки.

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