Справочный возврат для сеттера

A. Насколько полезным/громоздким является следующий прием использования одной и той же функции для получения и установки, возвращая ссылку?

B. Насколько хороша практика добавления const в конец объявлений функций в случае геттеров и сеттеров?

#include <iostream>

class A
{
  int varReadWrite_;
  int varReadOnly_;
  int varRestricted_;

public:
  A() : varReadOnly_(25) {}
  virtual ~A() {}

  int& varReadWrite() { return varReadWrite_; }
  int varReadOnly() { return varReadOnly_; }
  int varRestricted() { return varRestricted_; }
  void setVarRestricted(int i); //throwable

};

int main(int argc, char *argv[])
{
  A a;
  a.varReadWrite() = 45;
  std::cout << a.varReadOnly() << a.varReadWrite() << std::endl;
  return 0;
}

Причины, по которым я выбрал этот дизайн, были:

  1. простота доступа к явно доступным только для чтения или явно записываемым переменным.
  2. ограниченные (я не знаю, как еще их назвать), переменные, которые требуют очистки и фильтрации перед назначением - эти переменные могут потребовать явного установщика.

Использование ускорить карту fusion также является интересной возможностью, как здесь

Обновить

Const Reference Members интересны для доступа к переменным только для чтения, например.

class A {
  int mA;
public:
  int& a;
  A(int a_ = 0) : mA(a_), a(mA) {}
};

Практически это связано с дополнительными усилиями по кодированию конструкторов копирования и перемещения, что является приемлемым компромиссом для меня.

Cpp Reference Copy Construtor говорит

Неявно объявленный или заданный по умолчанию конструктор копирования для класса T определяется как удаленный, если... T имеет нестатические элементы данных, которые нельзя скопировать (удалены, недоступны, или неоднозначные конструкторы копирования);


person hell_ical_vortex    schedule 26.09.2015    source источник
comment
Это так же хорошо/громоздко, как использование общедоступной переменной-члена.   -  person πάντα ῥεῖ    schedule 26.09.2015
comment
Возврат ссылки обычно не считается хорошей практикой, так как пользователи могут удерживать ее, и вы не знаете, когда могут произойти изменения, и это усложняет проблемы со сроком службы.   -  person sje397    schedule 26.09.2015
comment
если никакое изменение переменной не может нарушить инвариант класса, сделать его общедоступным. если это не так, используйте правильные методы с описательными именами, вносите последовательные изменения и поддерживайте инвариант класса.   -  person sp2danny    schedule 26.09.2015


Ответы (2)


A. Насколько полезен/громоздкий следующий прием использования одной и той же функции для геттера и сеттера, возвращая ссылку?

Возвращать ссылку на ваши внутренние члены в целом не рекомендуется, так как таким образом вы предоставляете легкий доступ другим, чтобы они могли изменить внутреннее состояние вашего объекта без использования какого-либо метода, предоставляемого API класса объекта. Таким образом, отследить такого рода изменения в коде будет очень сложно. В целом изменения внутреннего состояния объекта должны быть возможны только с помощью методов, принадлежащих API класса.

B. Насколько хороша практика добавления const в конец объявлений функций в случае геттеров и сеттеров?

если вы ссылаетесь на добавление const для таких методов, как:

void PrintState() const

Тогда вообще это не имеет смысла для сеттеров. Const в данном случае означает Этот метод не изменяет состояние объекта. Таким образом, вы даете вызывающему абоненту обязательство сказать: Я не буду изменять состояние объекта этим вызовом. В общем, это очень хорошая практика, поскольку она помогает вам во время проектирования думать о своих методах и видеть, какой из них действительно изменяет состояние объекта, а какой нет. Кроме того, это защитное программирование, поскольку оно рекурсивно: если вы передаете этот объект какому-либо методу по ссылке (через указатель или ссылку), он не может вызывать константные методы, если этот метод также не помечен как константный. Таким образом, это предотвращает изменение состояния объекта по ошибке.

person rkachach    schedule 26.09.2015
comment
Спасибо за описательный ответ. Это дает мне представление о том, как мне следует подходить к конкретным задачам программирования. Я пока не могу говорить о разработке программного обеспечения, но я уверен, что могу помнить об этом, когда нахожусь там. - person hell_ical_vortex; 27.09.2015

Аксессоры (также известные как getters и setters) так же хороши/громоздки, как и наличие общедоступных переменных-членов, поскольку вы только что нарушили инкапсуляцию и солгали сами. Смешивать их в одной функции еще хуже, так как вызывающая сторона может удерживать возвращаемую ссылку, открывая дыру для еще более тонких ошибок, чем описано в ссылке выше.

Во-вторых, добавление const в объявление функции-члена защитит вас от setters, но не от getters. В любом случае, планируйте свои проекты лучше :).

person 3442    schedule 26.09.2015
comment
Спасибо за ссылку. Это было познавательно. Я не мог понять изменения дизайна, предложенные для старых простых структур. А также о том, что считается плохим/опасным/грязным в их использовании в шаблонном метапрограммировании. Здесь можно спросить или новую тему открыть. - person hell_ical_vortex; 27.09.2015
comment
@bvraghav: Здесь все в порядке, потому что это касается одного из моих предыдущих ответов. Что я пытался сказать о POS (обычных старых структурах), так это то, что их следует использовать в двух случаях. Прежде всего, когда их единственной целью является хранение простых данных (без непосредственно связанного кода), которые относятся к единице перевода (также известной как файл .cpp). Второе использование происходит всякий раз, когда вы занимаетесь метапрограммированием шаблонов, где они просто бесценны с точки зрения дизайна. ПРОДОЛЖЕНИЕ. - person 3442; 27.09.2015
comment
@bvraghav: ПРОДОЛЖЕНИЕ. Дело в том, что (в большинстве случаев) при использовании в метапрограммировании шаблонов они вообще не содержат данных, ни связанного кода, потому что нет связанных данных. Обычно они содержат такие вещи, как typedefs или constexpr size_ts. В данном случае использование classes просто глупо, потому что инкапсулировать вообще нечего. Пожалуйста, прокомментируйте здесь, если у вас есть какие-либо другие сомнения, связанные со ссылкой :). - person 3442; 27.09.2015
comment
Понял - оба. Однако мне любопытно, почему вы называете файл .cpp единицей перевода? - person hell_ical_vortex; 28.09.2015