Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.60/30: Рейтинг темы: голосов - 30, средняя оценка - 4.60
9 / 9 / 0
Регистрация: 10.11.2011
Сообщений: 241
1

Свойства класов - зачем помещать свойство в приват

01.04.2012, 18:23. Показов 6039. Ответов 54
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Очень часто встречал такие классы
C++
1
2
3
4
5
6
7
8
claas A
{
 public:
  int getCount( void ) { return count; };
  void setCount( int c ) { count = c; };
 privte:
  int count;
}
Но зачем помещать свойство в приват и затем делать 2 лишних метода для работы с ним? Почему бы не поместить это свойство в паблик и не работать с ним на прямую? Просто если так делают значит есть этому логическое обьяснение, и хочется его понять.

PS. тут ещё мысля возникла, если в Си (не C++, а простой Си) небыло оператора new то получается небыло утечек памяти?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.04.2012, 18:23
Ответы с готовыми решениями:

Зачем свойство !hover в QSS
Доброго времени суток, зачем свойство !hover в стилях, если можно обойтись простым QPushButton{}? ...

Зачем нужно свойство @property (assign)
Для чего нужно свойство property (assign)? Как мне обратиться к полю класса, если оно под...

Свойство column свойства margin
Есть свойства: p { column-count: 4; /*Количество колонок в многоколоночном тексте*/ ...

Зачем всегда инкапсулировать переменные в свойства
Давно хотел спросить. Вопрос возникает постоянно, когда я вижу код типа такого: class cls {...

54
быдлокодер
1724 / 911 / 106
Регистрация: 04.06.2008
Сообщений: 5,679
02.04.2012, 10:39 41
Author24 — интернет-сервис помощи студентам
Ну я их путаю сеттеры и геттеры
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
02.04.2012, 13:06 42
Там где-то в начале вопрошалось о косяках класса Vector3D. А вот они, степень важности от безразличной, до неработоспособности программы (сверху-вниз по файлу):
- Конструкторы не используют списки инициализации
- Методы cross, dot должны быть константными.
- Операторы +/- должны быть функциями, а не методами. Но в данном случае это не критично, т.к. нет преобразовывающего конструктора.
- operator [] не работоспособен. Ты удивишься, но выравнивание на 4 байта уже стало большой редкостью. Данный метод в двух случаях из трёх вернёт мусор.
- float * , то же, что и выше.
- Большинство методов должны быть функциями в пространстве имён этого класса
- Одни и те же операторы объявлены и как методы и как функции.

Как-то так.
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,495
Записей в блоге: 1
02.04.2012, 13:23 43
Цитата Сообщение от silent_1991 Посмотреть сообщение
Kuzia domovenok, ну, если не учитывать, что мои геттеры/сеттеры так не выглядят, потому что список инициализации можно использовать только в конструкторе, то довольно редко. Потому что у меня классы обычно представляют поведение, а не данные, как и должно быть. Сами классы могут пользоваться несколько более высокоуровневыми данными, чем сырые данные стандартных типов, но такие данные я оборачиваю в структуры, описанные внутри классов, в приватной области. Если класс состоит из одних данных и методов доступа, т.е. представляет данные, то надо пересмотреть надобность использования класса.
Да, да, понял, лоханулся с инициализацией. Признаю это. И так же признал бы необходимость в сокрытии всех полей классов, если бы увидел аргументы в пользу сокрытия.
Но пока что всё, к чему вы пришли это "для отладки". Я, как новичок, считаю, что лучше всего учиться на примерах. Но все примеры, которые я видел меня пока не убеждают. Ну, вот хотя бы этот ваш "контроль диапазона присваемого". Ну скажите, зачем мне ограничивать диапазон в классе Vector3D??? Что вообще может быть в сеттере вектора, кроме x=tx;y=ty... ? Прочитайте первый пост! Речь же шла именно о таких ситуациях, когда нечего написать в сеттере, кроме сеттинга!
Или вот обругали тут этот класс за говнокод. Ну и что, но он же работает? В этом то и основной вопрос ТС. Зачем ораничиать самого себя в доступе (себя, а не мифических "других пользователей", которых во многих программах, особенно учебных и не существует).
И не надо тут давить авторитетом "публикаций". ТС привёл конкретный пример геттера/сеттера, которые ничего не делают. Что мешает вместо этого сделать поле публичным? Покажите публикацию, которая требовала бы создавать такие пустые гетсеттеры.
И опять заводите речь о "больших и сложных программах". Но как показывает практика, немалая часть программистов пихают прайват поля даже в простые программы. Или вы даже разрабатывая "Тетрис" завернёте все данные в приватные поля классов?
- operator [] не работоспособен. Ты удивишься, но выравнивание на 4 байта уже стало большой редкостью. Данный метод в двух случаях из трёх вернёт мусор.
ОК, принимается. В двух случаях из трёх я с тобой соглашусь.
- Методы cross, dot должны быть константными.
Ты всегда объявляешь константным любой метод, который не изменяет поля? Вообще, в чём суть объявления метода константным? Чтобы он мог вызываться у констант?
- Большинство методов должны быть функциями в пространстве имён этого класса
Ну так продолжай мысль, где проходит грань при выборе сделать функцию методом класса или другом или в пространстве имён?
- конструктор копирования не делает ничего, чего бы не сделал генеренный компилятором, не нужен
Согласен, некоторые "сетгеттеры" не нужны по этой же причине.
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
02.04.2012, 13:38 44
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Ты всегда объявляешь константным любой метод, который не изменяет поля?
Именно так.
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Чтобы он мог вызываться у констант?
Именно так. Поэтому все переменные, которые не могут (не должны, но все мы люди) изменяться я делаю константными.
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
в чём суть
Как и 90% всего кода - самодокументирование. Называя метод Get* и не делая его константным - ты врёшь самому себе. Создавая не константный метод, который не изменяет инвариант класса - ты врёшь себе. Создавая метод, который должен быть функцией, ты себе не врёшь, но помещаешь в интерфейс класса то, что не является частью его интерфейса, а это уже ошибка.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Ну и что, но он же работает?
Индусы с тобой согласны, да. У них тоже "всё работает".

Добавлено через 1 минуту
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
где проходит грань при выборе сделать функцию методом класса или другом или в пространстве имён?
То, что является интерфейсом класса, должно быть в интерфейсе класса. То, что не является интрфейсом класса, должно не быть функцией в пространстве имён класса.
2
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,495
Записей в блоге: 1
02.04.2012, 13:49 45
Ага, а разрабатывая "Тетрис" вы тоже завернёте в него 100500 приватных полей, "на всякий случай", "чтобы случайно всё не испортить". Вместо того, чтобы взять и забыть про ООП на время разработки простой программы.

Вопрос стоял о данных, которые вы объявляете приватными, но тут же открываете к ним доступ гетсеттерами.
То, что является интерфейсом класса, должно быть в интерфейсе класса. То, что не является интрфейсом класса, должно не быть функцией в пространстве имён класса.
Ну вот, представьте: разрабатываете вы Тетрис, программу у вас от силы из 5-6 функций. Зачем её усложнять?
В чём отличие в применении
C++
1
void Shape::draw()
От
C++
1
friend void draw(Shape*)
??? Для меня никакой.
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
02.04.2012, 14:13 46
Kuzia domovenok, Хм. Ну. Желательно бы нечто вроде.

C++
1
IDrawer::draw(const std::shared_ptr<Shape>& shape);
1
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
02.04.2012, 14:14 47
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
В чём отличие в применении
В том, что draw это часть интерфейса и должна быть методом. Более того, виртуальными могут быть только методы, а draw это именно виртуальный метод (то, что у тебя не виртуальный, это упущение при проектировании, ты бы исправил эту ошибку чуть позже).

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
но тут же открываете к ним доступ гетсеттерами
Ты не открываешь к ним доступ.
Там выше где-то был пример с полями a,b,c и методами доступа гарантировалось, что с равно сумме a и b. Так это ошибка проектирования. Поле с там вообще не нужно, т.к. оно вычисляется из a и b. Т.е., когда разработчик обнаружит эту ошибку, он просто удалит поле с и исправит реализацию пары методов и ему не придётся изменять 100500 вызовов этих методов. А что бы пришлось делать, если бы непосредственно обращение происходило к полю с? Как использовать переменную, которой больше нет? Пришлось бы везде писать a+b или вводить таки новую функцию.
А теперь представь, что это всё происходит в dll, которой пользуется куча народа. Сколько матерных слов ты услышишь в свой адрес из-за того, что им придётся рефакторить все свои приложения?

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
В этом то и основной вопрос ТС
В первом посте ТС нтерфейс класса ошибочен. Начиная с не виртуального деструктора и заканчивая методом set* для изменения счётчика.
1
Модератор
Эксперт PythonЭксперт JavaЭксперт CЭксперт С++
12458 / 7482 / 1753
Регистрация: 25.07.2009
Сообщений: 13,762
02.04.2012, 14:36 48
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Я, как новичок, считаю, что лучше всего учиться на примерах. Но все примеры, которые я видел меня пока не убеждают.
Точно все посты читаете? silent_1991 в 37 посте привёл очень даже жизненный пример, как соблюдение простого негласного правила и написание пары "лишних" строчек кода может спасти от внесения правок везде, где использовалась свежеизменённая часть класса.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Или вот обругали тут этот класс за говнокод. Ну и что, но он же работает?
Можно проехать метров 50 за рулём автомобиля с закрытыми глазами и при определённом везении никого не покалечить. Но если зажмуриваться во время вождения более-менее регулярно, обязательно станешь героем увлекательного квеста с участием ГИБДД, МСЧ, etc... (опять же, если повезёт)...

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
И не надо тут давить авторитетом "публикаций".
Попытки "давить авторитетом", если не ошибаюсь, начались со ссылки на абы как написанный класс вектора в трёхмерном пространстве.
1
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
02.04.2012, 14:59 49
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
всё, к чему вы пришли это "для отладки"
Я?? Где? О_о
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Я, как новичок
О чём же вы тогда можете спорить?
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Ну и что, но он же работает?
После этих слов вас сложно воспринимать всерьёз. Вас не возьмут работать в гугл.
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Зачем ораничиать самого себя
Да как же вы не поймёте, основная причина, по которой появилось ООП - повторное использование кода не через копипаст. Я, например, писал как-то на втором курсе один класс чисто для себя, не предполагая его никому показывать. Если бы я там наговнокодил, так бы он и валялся в папочке со старыми проектами. Но я старался сделать всё по фэншую. И что теперь? После минимального рефакторинга (по сути переписывание некоторых мест под новый стандарт) я вставил его в диплом. Вот вам и учебная программа. Профессиональный программист не разделяет программы на "трукод для всеобщего обозрения" и "говнокод для себя".
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
И не надо тут давить авторитетом "публикаций"
Оу-оу, от кого я это слышу?
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Ты всегда объявляешь константным любой метод, который не изменяет поля? Вообще, в чём суть объявления метода константным? Чтобы он мог вызываться у констант?
Естественно. Погуглите "принцип наименьших привилегий".

Добавлено через 2 минуты
Цитата Сообщение от kravam Посмотреть сообщение
не пойдёт. Ты вызовешь самый правильный суперпупергеттер в ненужном месте и весь код насмарку. Это я и называю (и оно по-моему такое и по сути)- ошибочно изменить поле класса.
Я это называю нажать педаль газа вместо тормоза. Тут уж никто не гарантирует программиста от его собственной тупости.
2
Эксперт JavaЭксперт С++
8384 / 3616 / 419
Регистрация: 03.07.2009
Сообщений: 10,709
02.04.2012, 15:02 50
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Но пока что всё, к чему вы пришли это "для отладки". Я, как новичок, считаю, что лучше всего учиться на примерах. Но все примеры, которые я видел меня пока не убеждают.
Использование ацессоров для отладки - это огромное преимущество, но не только для этого они нужны. Простой пример из реального проекта. Представьте, что у вас есть класс и вам нужен триггер на изменение какого-то из полей. Что вы будете делать? Будете выворачивать свой класс наизнанку и каждый раз заново расписывать аналог триггера или же просто в сеттере вызовите нужный обработчик? Еще один пример - у вас есть некая ентити. У вас есть некая мапа ченджей данных в этой энтити. Как вы будете отлавливать изменение? А я просто добавлю в сеттере код, который будет отображать изменение данных в мапе.

Цитата Сообщение от silent_1991 Посмотреть сообщение
После этих слов вас сложно воспринимать всерьёз.
да ладно тебе. Все так учатся. Сначала "лишь бы класс работал", потом "лишь бы выполнял поставленную задачу", позже "как бы эффективнее выполнял задачу", а только потом "как сделать так, чтобы он эффективно выполнял задачу и был масштабируемым". У него все еще впереди
0
silent_1991
02.04.2012, 15:09
  #51

Не по теме:

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

0
fasked
02.04.2012, 15:27
  #52

Не по теме:

Цитата Сообщение от silent_1991 Посмотреть сообщение
что "чк" и "чн" пишется с мягким знаком потому, что мой друг-гопник их так пишет.
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Например класс Vector3D я бы спокойно совершенно объявил так:
В этих ваших интернетах как только не понапишут.

0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
02.04.2012, 15:29 53
Цитата Сообщение от Deviaphan Посмотреть сообщение
о, что не является интрфейсом класса, должно не быть функцией в пространстве имён класса.
Должно БЫТЬ функцией, разумеется... Лишнее НЕ написал.
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,495
Записей в блоге: 1
02.04.2012, 18:40 54
[QUOTE]IDrawer::draw(const std::shared_ptr<Shape>& shape);[QUOTE]
Ой, вот только не надо этих извращений. Мы на первых страницах определились, что программа пишется в одиночку, и не претендует на звание "универсальногововсесторонырасширяемого движка".
Смысл тогда плодить в ней сущности?
В том, что draw это часть интерфейса и должна быть методом. Более того, виртуальными могут быть только методы, а draw это именно виртуальный метод (то, что у тебя не виртуальный, это упущение при проектировании, ты бы исправил эту ошибку чуть позже).
Ой, теперь ещё одна тема разговора появилась, про виртуальные функции.
Давай не будем о них, об интерфейсах и виртуальности. просто потому что нигде не сказано, что у меня класс Shape абстрактный и взят из известного Страуструпповского примера. Может я имел в виду вполне конкретный Шейп?
(то, что у тебя не виртуальный, это упущение при проектировании, ты бы исправил эту ошибку чуть позже)
Ну почему же ошибка. Применение чисто виртуальных функций не самое широкое. Изредка создаёшь интерфейс поведения для какого-нибудь класса объектов. Изредка создаёшь какой-нибудь список разносортных объектов для отрисовки. Но это довольно узкоспециализированная область применения.
Ты не открываешь к ним доступ. Там выше где-то был пример с полями a,b,c
Да это я писал, как одно из редких применений приватных полей, на мой взгляд. Не помню, где я прочитал этот пример. Казалось в Страуструпе, но сейчас проверил - там нет. И на мой взгляд, не такое уж бесполезное. Например, если C равно не сумме, а какой-то сложной функции от а и б, которую все хотят получить, а а и б при этом редко изменяются.
А что бы пришлось делать, если бы непосредственно обращение происходило к полю с?
Вот и я спрашиваю, что? Ну переписали бы осращение к нему из item.c в item.getc() или на что там ты хотел заменить? более того, заменять всё равно придётся, а от того, что функция getC изменится в ходе разработки с int getC(){return C;} на int getC(){cerr<<"Megafatalerror";return -1;}тем кто использует эту функцию легче не станет. Всё равно ошибку придётся исправлять рано или поздно.
А теперь представь, что это всё происходит в dll, которой пользуется куча народа.
Я не писал ещё dll, которой пользуется куча народу. Более того, я видел примеры классов, которыми НЕ пользуется куча народа, а у автора всё равно не проходит private синдром: добавить поритруемости, масштабируемости... А может не надо нам так трясти этим прям везде-везде?
Представьте, что у вас есть класс и вам нужен триггер на изменение какого-то из полей. Что вы будете делать? Будете выворачивать свой класс наизнанку и каждый раз заново расписывать аналог триггера или же просто в сеттере вызовите нужный обработчик?
Да, здесь добавлю сеттер, а затем выверну код наизнанку, добавляя его использование. не так и много времени это займёт, пожалуй.
Но мне всё равно кажется, что такие механизмы, как использование триггеров, планируются до того, как мы решили создавать этот класс.
0
Делаю внезапно и красиво
Эксперт С++
1313 / 1228 / 72
Регистрация: 22.03.2011
Сообщений: 3,744
02.04.2012, 18:57 55
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
и взят из известного Страуструпповского примера
Мне стыдно, но я не читал Страуструпа и не знаю, о каком примере идёт речь. Но класс Shape не может быть конкретным по определению, т.к. с таким названием он может быть только базовым. Отсюда и все следствия.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
и не претендует на звание "универсальногововсесторонырасширяемого движка"
Где ты взял сложность? Это просто альтернативный подход. Если метод Draw не является интерфейсом данного класса, то он может быть частью интерфейса другого объекта, который умеет рисовать объекты заданных типов. Никакой сложности и мегауниверсальности, просто иной взгляд на проблему.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Может я имел в виду вполне конкретный Шейп?
Тогда ты "очень плохой программист", если такие названия классам даёшь.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Применение чисто виртуальных функций не самое широкое.
Особенно в ООП, да.
И о чисто виртуальных я слова не говорил.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
если C равно не сумме
Я там подробно описал. Если с сложновычисляемая производная, то она кэшируется. При этом кэш не определяет инвариант.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
тем кто использует эту функцию легче не станет
А ты чувствуешь разницу между "нажать F7" и "провести рефакторинг кода, заменить обращения к переменной с на вызов метода и нажать F7"?

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
А может не надо нам так трясти этим прям везде-везде?
Привычка вырабатывается за 21 день (это из курса психологии). Потом делать начинаешь не задумываясь. Если при обучении будешь делать абы-как, рисуя всякую непотребщину изо-дня в день, то ты привыкнешь так писать и будешь писать так всегда. Переучить толстолобика практически невозможно (требуется уже больше 21 дня). Поэтому делать ПРАВИЛЬНО нужно сразу же, начиная с Хеллоу Ворлда.

Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Я не писал ещё dll, которой пользуется куча народу
А я писал, поэтому поверь на слово.


Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
не так и много времени это займёт, пожалуй.
Я вот щяс рефакторил програмульку... Всего полторы тысячи файлов... Знаешь... много времени исправление таких "мелочей" занимает. Очень много.
3
02.04.2012, 18:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.04.2012, 18:57
Помогаю со студенческими работами здесь

Зачем нужны автоматически реализуемые свойства?
Зачем нужны автоматически реализуемые свойства в c#? Что, нельзя просто пометить поле как public?...

Зачем нужны автоматические свойства? {get; set}
Я прочел все темы в этом форуме касательно свойств. Но никто толком не может ответить зачем нужны...

Зачем использовать поля, если есть свойства?
Приветствую. Объясните новичку: для чего нужно использовать поля, если есть такая штука, как...

Как назначить свойства блоку div через свойство SetAttribute?
Здравствуйте, уважаемые форумчане! Обращаюсь сюда, потому что возникла проблема: не получается...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
55
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru