2010-11-06 3 views
6

Иногда мне нужно выставить некоторые из членов класса. Например, в следующем примере class Mechanic может потребоваться прямой доступ к компоненту Engine. Я много раз читал, что все поля должны быть доступны с помощью методов mutator (accessor) по нескольким причинам. Но есть ли какое-либо преимущество при предоставлении неконстантного ссылочного поглотителя:Имеет ли смысл предоставлять неконстантную ссылку getter

class Car 
{ 
    public: 
     Engine & engine() 
     { 
      return m_engine; 
     } 

     //as a consequence you will also need to provide const version 
     const Engine & engine() const 
     { 
      return m_engine; 
     } 

    private: 
     Engine m_engine; 
} 

более просто делают компонент двигателя общественности:

class Car 
{ 
    public: 
     Engine engine; 
} 

Вы также можете заменить public с protected, если вам не нравится этот пример. В реальной жизни у вас есть что-то simillar на Java, когда дело доходит до System.in или System.out. Похоже, чтобы быть полностью совместимым с тем, что говорят некоторые люди, вам нужно будет выполнить такие вызовы, как System.getInstance().getOut().println("hello world"). В таких случаях я не вижу никакой пользы, кроме большого количества бюрократического кода.

+0

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

+0

@Steve Jessop: Не будьте так ревностны, сортируйте вопросы по голосам, и вы получите много неточных (вопрос не может быть субъективным, ответ может быть). Каждый ответ более или менее субъективен. В оправдание ваших подозрений - я был в поездке, и у меня не было возможности посетить stackoverflow в последнее время. – doc

+0

вот почему я не уверен. Если кто-то искренне просит причины для чего-то, я думаю, что все в порядке, хотя нет никакой определенной причины. Если кто-то не верит, что есть какие-то причины, но все равно спрашивает о причинах, я думаю, что «обычно приводит к конфронтации и аргументации». Никакой серьезный вред не нанесен в любом случае, но последний не является целью сайта AFAIK. –

ответ

1

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

3

Они могут быть полезны, когда значение, которое вы возвращаете, фактически находится в куче.

template<class T> class Singleton 
{ 
private: 
    static T* m_pSingleton; 

public: 
    T& getSingleton() { assert(m_pSingleton); return(*m_pSingleton); }; 

}; // eo class Singleton 
+3

Определенное сокращение для шаблона Singleton. – Puppy

+2

А, я помню времена, когда образ Синглтона был в ярости ... Черт, я даже помню, когда PEEK и POKE были в ярости. :-) – Gorgen

+4

Да, массивы злы, геттеры и сеттеры злы, одиноки - злые, цельное программирование - зло. Лучшие программисты - это те, кто не написал кусок кода. +1, потому что иногда полезны синглтоны. – doc

0

Для меня это имеет смысл здесь:

image(i,j) = 234; 
1

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

+1

Если вы предоставляете поле и позже меняете его на геттер, клиентский код не просто перекомпилируется, он должен быть перезаписан. –

3

Явные геттеры и сеттеры могут быть чрезмерно бюрократическими; это зависит от вашей ситуации.

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

Если ваш класс, если он очень простой (например, близкий к POD) и вряд ли изменится, то, возможно, не стоит того, чтобы внедрять геттеры и сеттеры.

Однако, чтобы ответить на ваш вопрос, неконстантный геттер, вероятно, не имеет большого смысла. Ваш прототип геттера должен быть Engine & engine() const; иначе вы не сможете позвонить по телефону constCar объектов.

+1

Для лучшего поиска в Google это называется * инкапсуляцией *. –

+1

Я исправил пример. Должны быть две версии 'engine()' method: const и non-const. По-моему, иногда бывает удобно разоблачить участников и отменить инкапсуляцию. – doc

0

Вместо того, чтобы думать о том, чтобы подвергать частные члены класса, подумайте больше о методах вызова на этих классах. Я прочитал интересную статью Java, Why Getter and Setter Methods are Evil, которая так же применима к C++, как и к Java.

+0

Да, я прочитал это и написал комментарий под названием «Теория - это просто теория» :) Я хочу сказать, что код состоит из операций и данных, а не только кода. Как-то вам нужно изменить данные, поэтому статья явно ошибочна. Автор не видит большой картины за компьютерами. Он закрепил некоторые принципы, построенные на вершине, называемые объектно-ориентированным программированием. Но ООП не существует без процедурного программирования. – doc

+0

@doc: Если это бесполезно, зачем беспокоиться о том, что говорит теория в первую очередь? Что касается компьютерных моделей, то теория не является абстрактной математической концепцией, которую вызывает какой-то мечтатель (прочитайте «На первом этапе проектирования»). Они рождаются по необходимости (из-за проблем, возникающих на практике). Ваша проблема - одна из них. Поэтому, когда кто-то говорит: «Геттеры и сеттеры злы», это не похоже на «1 == 1». – nakiya

1

Как я случайно получил образование в последнее время, геттеры и сеттеры пахнут плохим дизайном.Но, если вы так хотите, предоставляя функции для получения и установки m_engine (определенные вами), а не просто выставляя его (у вас нет вмешательства), вы должны иметь плагин для будущих изменений.

+0

Как вы можете реализовать, скажем, 'class Window' с его шириной, высотой и некоторыми другими свойствами без геттеров и сеттеров? Разве мы не сходим с ума? Большинство объектов реальной жизни похожи на «класс Window»; почти простые структуры, заполненные некоторыми методами. Я встретил дизайн с несколькими аксессуарами (хотя 'Window' получил свои методы GetWidth или GetSize) в виде библиотеки SFML, и из-за этого я не смог хорошо расширить свои классы. – doc

+0

В моем ответе было два момента. Первое: инкапсуляция хороша. Во-вторых, если у вас не может быть первого, то геттеры и сеттеры хороши. Идея второго сценария состоит в том, чтобы избежать дублирования кода, которое может произойти в будущем (или прямо сейчас), если вы хотите применить какое-либо ограничение на 'ширину или высоту окна. В первом пункте, в то время как сеттеры могут быть извинены, почему вам нужны геттеры? Разве это не означает, что вы предпочтете, чтобы этот бит данных получал геттер снаружи? Если это в классе, то почему другие могут вмешаться в него (почему даже предоставляют константы-константы)? – nakiya

+0

В вашем вопросе вам следует передать объект 'Механик' в объект' Car', чтобы объект 'Car' мог передать свой объект' Engine' объекту 'Mechanic'. Таким образом, вы устраняете геттер, а «Террорист» не сможет получить доступ к движку «Автомобиля». – nakiya

0

Да, это имеет смысл - для удобства обслуживания, проверки и согласованности.

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

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

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

0

В этом случае вы бы скорее нужен Car.fix(const Mechanic&) функцию, которая затем дает двигатель к Mechanic, сказать: Engine.fix(const Mechanic&), как я полагаю, что состояние Engine будет изменен.

Первоначальная идея использования классов состояла в том, чтобы связать данные с его функциями доступа. Если вы используете setter или getter, который просто возвращает внутренние данные, это означает, что ваши данные не связаны вместе со своими функциями доступа: ваш класс не завершен.

Вы хотите только показать новые данные, которые класс испускает. Скажите Car.get_exhaust() и Car не имеет выхлопных газов, производит только его, когда вы спрашиваете об этом. ;)

Или Fire Riefle.fire() в то время как нет доступа к Riefle::Trigger не будет зафиксирован механиком, как так: Trigger.fix_by(Mechanic), а затем fix_by позвонит сказать Mechanic.add_working_hour(0.5). XD

 Смежные вопросы

  • Нет связанных вопросов^_^