Получить / Установить в мире c ++, подделка? - PullRequest
14 голосов
/ 17 декабря 2008

Я заметил, что get / set - это не способ c ++, насколько я могу судить, взглянув на boost / stl и даже читая труды некоторых ведущих экспертов по c ++.

Кто-нибудь использует get / set в своем дизайне класса c ++, и может ли кто-нибудь предложить практическое правило, где, если вообще эта парадигма принадлежит миру c ++?

Очевидно, что он очень популярен в Java и имитируется c # с использованием свойства синтаксического сахара.

EDIT:

Хорошо, прочитав об этом больше по одной из ссылок, приведенных в ответе ниже, я наткнулся, по крайней мере, на один аргумент за то, что у аксессоров поля члена должно быть то же имя, что и у поля члена. А именно, что вы можете просто представить поле члена как public и вместо этого сделать его экземпляром класса, а затем перегрузить оператор (). Используя set / get, вы заставите клиентов не только перекомпилировать, но и фактически изменить свой код.

Не уверен, что мне нравится эта идея, мне она кажется слишком мелкой, но более подробная информация здесь:

C ++ Убил геттера / сеттера

Ответы [ 12 ]

13 голосов
/ 17 декабря 2008

C ++ не имеет таких свойств, как C #. Можно написать методы с «get» и «set» в их именах, но они не создают свойства автоматически. Так значит ли тогда использовать методы get и set?

Использование методов get и set в C ++ неплохо для доступа к свойствам класса. STL и Boost (на который оказал влияние STL) просто выбрали один дизайн - прекрасно иметь другой дизайн для ваших классов.

На моей работе мы используем get и set. Причина в первую очередь в том, что это позволяет писать синтаксические анализаторы для автоматического переноса классов C ++ с помощью других интерфейсов - ActiveX, .NET, LabVIEW, Python и т. Д. ... При использовании IntelliSence Visual Studio (и аналогичных технологий в других средах разработки) Я считаю, что использование методов get и set облегчает поиск того, что мне было проще. Поэтому бывают случаи, когда выгодно использовать методы get и set.

Самое важное - выбрать стандарт стиля кода для вашей библиотеки и соответствовать ему.

7 голосов
/ 17 декабря 2008

Инкапсуляция является концепцией ООП и применяется ко всем языкам ООП. Открытые члены данных нарушат инкапсуляцию. Это может быть хорошо, если у вас есть очень простой объект, который не требует инкапсуляции, однако эти ситуации являются исключением, и как только вы примете решение, может быть трудно вернуться и отменить его.

Для большинства объектов вам понадобятся геттеры и сеттеры, но вы всегда должны учитывать, как объект будет фактически использоваться при их написании. Boost и STL полны геттеров и сеттеров, они просто не используют имена «get» и «set», вместо этого они используют такие имена, как «длина», «конец», «резерв», «емкость» и т. Д. не используйте слова get или set, потому что эти функции служат не просто установке значения в объекте.

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

6 голосов
/ 17 декабря 2008

Вы можете определенно использовать средства доступа в C ++. Это хорошая статья о создании хороших схем доступа. В соответствующей статье также показан простой вспомогательный класс мета-аксессора, который поможет вам определить эти умные аксессоры тривиально.

5 голосов
/ 17 декабря 2008

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

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

1 голос
/ 01 июня 2009

Будем немного дидактичны здесь ...

У аксессоров есть два аспекта:

  • Работа в синтаксисе языка
  • Цель общения

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

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

Самым сложным аспектом является передача намерений, и способ сделать это - придерживаться идиом языка. К сожалению, в C ++ синтаксис несколько мешает этому, поэтому у нас есть такие вещи, как .size () для коллекций и .first и .second для пар. Все они являются аксессорами, но синтаксис меняется в зависимости от реализации - ой.

Теперь eJames говорит о том, что публичные члены нарушают инкапсуляцию. Является ли член публичным или нет, не имеет ничего общего с инкапсуляцией. Инкапсуляция - это продукт проектирования объектов и элементов управления, доступных для дизайнера классов на языке, который они используют. Это то, что я более подробно изучил в статье «Инкапсуляция - хорошая вещь ™» (этот сайт пока не позволит мне добавить ссылку, но, думаю, это не так уж сложно для Google).

Что оставляет нас в том, что в C ++ производный атрибут должен использовать синтаксис вызова метода. Не производное поле не обязательно, но вы можете выбрать, если хотите. Если вы используете синтаксис вызова метода, вы должны написать метод-оболочку самостоятельно. Не сложно, но это, безусловно, добавляет к количеству строк. Я попытался показать способ использования языка шаблонов C ++ для абстрагирования кода доступа. Это не совсем успешно, но оно справляется со многими вариантами использования.

Что касается того, должны ли мы использовать средства доступа или нет, то проблема в том, что синтаксис C ++ навязывает нам как разработчикам различие между доступом к простым членам и доступом к методам. Это раздражает, но у нас есть некоторые инструменты, чтобы что-то с этим сделать.

Как разработчик библиотеки, я обнаружил, что всегда использование синтаксиса вызова методов помогает мне создавать более надежные API, потому что, если я обнаружу, что хочу заменить простой элемент чем-то более сложным, то это дает мне больше возможностей, которые не делают требует довольно много синтаксиса. Помните, я мог бы абстрагироваться другим способом и сделать «функцию» похожей на значение путем подходящего использования операторов приведения и операторов присваивания - на самом деле, возможно, я попробую это и посмотрю, как я к этому отношусь:)

1 голос
/ 18 декабря 2008

Я почти всегда использую методы get / set, главным образом потому, что вы можете установить для них точки останова и выяснить, где задан элемент данных (или к нему обращаются, хотя это встречается реже). Кроме того, вы можете добавить отладочные утверждения внутри процедуры установки (и процедуры получения, хотя это менее полезно), чтобы убедиться, что объект находится в допустимом состоянии при установке значения.

Это также полезно, если вы создаете подкласс; иногда подкласс хочет выполнить некоторые вычисления, а не просто перенастроить значение. Сделать подпрограмму получателя виртуальной, а затем переопределить ее в подклассе - это просто.

1 голос
/ 17 декабря 2008

У меня, как правило, есть геттеры и сеттеры, я просто не склонен называть их "getX и" setX ", обычно я делаю что-то вроде этого, например:

int x = o->x() // getter
o->setX(5); // setter

Я обнаружил, что наличие получателя просто будет названием "свойства", просто читается лучше.

1 голос
/ 17 декабря 2008

Я не знаю, рекомендуется ли это использовать или нет, но я регулярно использую функции get / set в своих классах C ++, и я пишу код C ++ уже более двух десятилетий. Я никогда не смотрел на Java или C #, поэтому я не подхватил привычку этих языков.

0 голосов
/ 18 ноября 2009

Даже если c ++ не поддерживает методы доступа к свойствам, имитируя их, мы не только улучшаем читаемость и не обеспечиваем инкапсуляцию, но мы предоставляем механизм управления для установки значения переменной или получения вычисленного значения для переменной. Так что это конечная цель аксессоров. Для достижения этих целей язык должен непосредственно поддерживать методы доступа. Период.

0 голосов
/ 17 декабря 2008

Я собираюсь принять некоторые догадки.

  • В C даже не было возможности получения / установки, поэтому существовала привычка использовать прямой доступ к членам, как в структуре. Привычка застряла в С ++.
  • C / C ++ всегда предпочитали скорость, и если бы существовал какой-либо шанс, что старый компилятор не будет корректно встроен, получатель / установщик получит штраф за скорость.

Ни одна из этих причин не является убедительной.

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