Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 25, средняя оценка - 4.96
OrmaJever
9 / 9 / 0
Регистрация: 10.11.2011
Сообщений: 241
#1

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

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

Очень часто встречал такие классы
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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.04.2012, 18:23
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Свойства класов - зачем помещать свойство в приват (C++):

Получить доступ в приват - C++
Не получается получить доступ к полям привата. Вот написал такой код на с++. #include <iostream> using namespace std; class...

Производные классы паблик и приват - C++
Здравствуйте, нужна помощь. Это пример из книги Лафоре ООП С++. Не могу понять почему программа работает, хотя при наследовании классы...

Наследование класов - C++
Классы для меня в целом очень сложно даются, мне очень нужна данная прога так как все последующие лабораторные будут с ней связаны,...

наследование класов - C++
Напишите пожалуйста ету програму, а то я никак немогу разобратся с наследованием. Создать класс колесо, имеющее радиус. Определить...

Проверка наследования класов - C++
У меня есть один базовой клас "Creature", от него наследуються два класа "Animal" и "Plant". От класа "Animal" наследуються еще 2 класа...

Преобразование типов и методы класов - C++
Есть задача: 1)Создать класс Triangle, разработав следующие элементы класса: поля: int a, b, c; 2)Конструктор, позволяющий создать...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
villu
203 / 204 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
01.04.2012, 23:52 #31
а везде и не надо совать.
В той же std есть pair, который структура

а вот такой вариант
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {
    int count;
public:
#ifdef _DEBUG
    void set(int new_val, char *file = get__FILE__(), int line=get__LINE__() ) {
        g_log_device() << "Change 'с' to  " << new_val << " " << file << ":" << line << "\n";
        if( new_val > MAX_VALUE ) throw std::runtime_error("Invalid value");
        count = new_val;
    }
#else
    void set(int new_val) {
        count = new_val;
    }
#endif
    int get() { return count;}
};
мне однажды очень много времени сэкономил и даже помог отловить бажину в железке. а класс, на сколько помню, у меня тогда просто данные с кардио-датчика содержал, то есть фактически несколько полей (как тот самый вектор x y z), которые можно было сделать структурой.
Тут же TC спрашивал о вариантах, где это полезно может быть, нет разве?
1
silent_1991
Эксперт С++
4964 / 3040 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
01.04.2012, 23:55 #32
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Kuzia domovenok, ну, если не учитывать, что мои геттеры/сеттеры так не выглядят, потому что список инициализации можно использовать только в конструкторе, то довольно редко. Потому что у меня классы обычно представляют поведение, а не данные, как и должно быть. Сами классы могут пользоваться несколько более высокоуровневыми данными, чем сырые данные стандартных типов, но такие данные я оборачиваю в структуры, описанные внутри классов, в приватной области. Если класс состоит из одних данных и методов доступа, т.е. представляет данные, то надо пересмотреть надобность использования класса.
4
Asya
Сообщений: n/a
02.04.2012, 00:25 #33
Скрытие определённых полей класса(инкапсуляция) - базовый принцип объектно-ориентированного программирования.
для справки:
Инкапсуляция (пакетирование) представляет собой механизм, связывающий вместе данные и код, обрабатывающий эти данные, и сохраняющий их от внешнего воздействия и ошибочного использования. Инкапсуляция позволяет создавать объект, являющийся логическим целым, включающим данные и код для работы с этими данными. Объект обеспечивает защиту против случайной или несанкционированной модификации частных (private) составляющих его членов. Закрытые данные или коды (методы) доступны только для других частей этого объекта и недоступны вне его. Открытая часть объекта предназначена для обеспечения контролируемого интерфейса его закрытой части.

проще говоря, это нужно для обеспечения защиты данных, которые не должны быть доступны пользователю на прямую. Например, телевизор: мы нажимаем только на определённые кнопки, которые выполняют те или иные функции. Мы же не имеем доступа ко внутренним компонентам телевизора, которые принимают участие в реализации команды. Ибо если мы будем иметь прямой доступ к важным частям телевизора, мы можем что-нибудь изменить и телевизор не будет работать. Так и с программой. Пользователя не должна волновать реализация. Главное, чтобы выполнялись его команды. А программист всегда получит доступ к защищённым данным, если ему нужно исправить неисправность или добавить какую-нибудь функцию. Вот как-то так
kravam
02.04.2012, 01:28
  #34

Не по теме:

Цитата Сообщение от Asya Посмотреть сообщение
мы можем что-нибудь изменить и телевизор не будет работать
умиляет... А то геттерами ты не можешь ничё ошибочно изменить...

0
silent_1991
Эксперт С++
4964 / 3040 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
02.04.2012, 01:29 #35
kravam, нет, если принять, что геттер написан верно и не пропустит неправильные данные. Отладка классов - отдельная история, мы говорим о законченном рабочем коде.
0
Buckstabue
175 / 124 / 6
Регистрация: 12.01.2012
Сообщений: 624
02.04.2012, 02:50 #36
ИМХО, сокрытие в первую очередь нужно, чтобы упростить отладку программы. Например, при моделировании органайзера, мы должны быть твёрдо уверены, что встреча, намеченная в декабре, может проходить только в числах от 1 до 31. В то же время инкапсуляция позволяет делать программы более масштабируемыми. Например, если мы грамотно напишем обобщенный интерфейс доступа к базе данных, то в случае изменения самого сервера( или библиотеки ) БД нам придётся изменить код только в интерфейсе
0
silent_1991
Эксперт С++
4964 / 3040 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
02.04.2012, 02:54 #37
Цитата Сообщение от Buckstabue Посмотреть сообщение
В то же время инкапсуляция позволяет делать программы более масштабируемыми
Именно для этого она и существует. Например, в одной версии вектора размер может храниться отдельным полем, указатель на начало вектора - отдельным, а в другой могут храниться указатели на начало и конец вектора, а размер вычисляться как разность начала и конца (т.е. размер не хранится явным образом). Тогда реализации методов size будут различными, но если бы не инкапсуляция и методы доступа, то весь код типа "vec.size" лутул бы к чертям, потому что в новой версии класса вообще нету поля "size". Зато обращайся мы сразу через метод доступа, нам не важно, что в новой версии поменяли внутреннюю реализацию, ведь интерфейс, через который мы общались с вектором раньше, остался прежним.
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,460
02.04.2012, 03:07 #38
Цитата Сообщение от silent_1991 Посмотреть сообщение
kravam, нет, если принять, что геттер написан верно и не пропустит неправильные данные. Отладка классов - отдельная история, мы говорим о законченном рабочем коде.
не пойдёт. Ты вызовешь самый правильный суперпупергеттер в ненужном месте и весь код насмарку. Это я и называю (и оно по-моему такое и по сути)- ошибочно изменить поле класса.

И сразу же вопрос- большая ли разница чем ошибочно изменять поля класса- подобными вызовами геттеров или непосредственно обращаясь к полю, сделав его public? Разницы никакой, что так плохо, что эдак. Так что следите, что называется за руками, а не за уровнем доступа к полю.
0
easybudda
Модератор
Эксперт CЭксперт С++
9633 / 5581 / 948
Регистрация: 25.07.2009
Сообщений: 10,715
02.04.2012, 03:23 #39
А меня аргумент "потому, что так правильно" вполне устраивает, если произнесён кем-то сведующим в вопросе. Причины, по которым "так надо", станут понятны по мере приобретения опыта. Читаю книжку Perl Cookbook Тома Кристиансена и Натана Торкингтона (по мере прочтения проникся искренним уважением к авторам, к тому же в самой документации perl сплошь и рядом ссылки на эту книгу). В perl поддержка ООП вообще весьма своеобразно сделана. В частности нет стандартных средств языка для ограничения доступа к данным класса (что, в прочем не мешает истинным параноикам запрятать данные так, что захочешь - не доберёшься), но вот, что пишут авторы по этому поводу:
Работа методов зависит от того, как вы организуете открытый интерфейс к объекту. Нормальный класс не любит, чтобы окружающие копались у него во внутренностях. Для каждого атрибута данных должен существовать метод, обеспечивающий его чтение или обновление. Если пользователь пишет фрагмент вида:
Perl 6
1
2
3
$him = Person->new();
$him->{NAME} = "Sylvester";
$him->{AGE} = 23;
он нарушает интерфейс объекта и напрашивается на неприятности.
Ну а в С++, где есть способ запретить пользователю прямой доступ к данным класса, просто грех этим не воспользоваться. Разумеется, если класс не просто хранит значения переменной plain типа, при этом не заботясь о смысле и допустимости этих самых значений...
2
ForEveR
В астрале
Эксперт С++
7973 / 4735 / 321
Регистрация: 24.06.2010
Сообщений: 10,542
Завершенные тесты: 3
02.04.2012, 10:16 #40
kravam, Крайне интересно, это каким же макаром, вызов геттера может изменить нечто в классе? Геттер обязан быть константным методом, геттер обязан ничего не менять в классе. И тогда не будет таких проблем, которые вы описываете.
А вот сеттером изменить можешь.
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,460
02.04.2012, 10:39 #41
Ну я их путаю сеттеры и геттеры
0
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1287 / 1221 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
02.04.2012, 13:06 #42
Там где-то в начале вопрошалось о косяках класса Vector3D. А вот они, степень важности от безразличной, до неработоспособности программы (сверху-вниз по файлу):
- Конструкторы не используют списки инициализации
- Методы cross, dot должны быть константными.
- Операторы +/- должны быть функциями, а не методами. Но в данном случае это не критично, т.к. нет преобразовывающего конструктора.
- operator [] не работоспособен. Ты удивишься, но выравнивание на 4 байта уже стало большой редкостью. Данный метод в двух случаях из трёх вернёт мусор.
- float * , то же, что и выше.
- Большинство методов должны быть функциями в пространстве имён этого класса
- Одни и те же операторы объявлены и как методы и как функции.

Как-то так.
0
Kuzia domovenok
1891 / 1746 / 118
Регистрация: 25.03.2012
Сообщений: 5,925
Записей в блоге: 1
02.04.2012, 13:23 #43
Цитата Сообщение от silent_1991 Посмотреть сообщение
Kuzia domovenok, ну, если не учитывать, что мои геттеры/сеттеры так не выглядят, потому что список инициализации можно использовать только в конструкторе, то довольно редко. Потому что у меня классы обычно представляют поведение, а не данные, как и должно быть. Сами классы могут пользоваться несколько более высокоуровневыми данными, чем сырые данные стандартных типов, но такие данные я оборачиваю в структуры, описанные внутри классов, в приватной области. Если класс состоит из одних данных и методов доступа, т.е. представляет данные, то надо пересмотреть надобность использования класса.
Да, да, понял, лоханулся с инициализацией. Признаю это. И так же признал бы необходимость в сокрытии всех полей классов, если бы увидел аргументы в пользу сокрытия.
Но пока что всё, к чему вы пришли это "для отладки". Я, как новичок, считаю, что лучше всего учиться на примерах. Но все примеры, которые я видел меня пока не убеждают. Ну, вот хотя бы этот ваш "контроль диапазона присваемого". Ну скажите, зачем мне ограничивать диапазон в классе Vector3D??? Что вообще может быть в сеттере вектора, кроме x=tx;y=ty... ? Прочитайте первый пост! Речь же шла именно о таких ситуациях, когда нечего написать в сеттере, кроме сеттинга!
Или вот обругали тут этот класс за говнокод. Ну и что, но он же работает? В этом то и основной вопрос ТС. Зачем ораничиать самого себя в доступе (себя, а не мифических "других пользователей", которых во многих программах, особенно учебных и не существует).
И не надо тут давить авторитетом "публикаций". ТС привёл конкретный пример геттера/сеттера, которые ничего не делают. Что мешает вместо этого сделать поле публичным? Покажите публикацию, которая требовала бы создавать такие пустые гетсеттеры.
И опять заводите речь о "больших и сложных программах". Но как показывает практика, немалая часть программистов пихают прайват поля даже в простые программы. Или вы даже разрабатывая "Тетрис" завернёте все данные в приватные поля классов?
- operator [] не работоспособен. Ты удивишься, но выравнивание на 4 байта уже стало большой редкостью. Данный метод в двух случаях из трёх вернёт мусор.
ОК, принимается. В двух случаях из трёх я с тобой соглашусь.
- Методы cross, dot должны быть константными.
Ты всегда объявляешь константным любой метод, который не изменяет поля? Вообще, в чём суть объявления метода константным? Чтобы он мог вызываться у констант?
- Большинство методов должны быть функциями в пространстве имён этого класса
Ну так продолжай мысль, где проходит грань при выборе сделать функцию методом класса или другом или в пространстве имён?
- конструктор копирования не делает ничего, чего бы не сделал генеренный компилятором, не нужен
Согласен, некоторые "сетгеттеры" не нужны по этой же причине.
0
Deviaphan
Делаю внезапно и красиво
Эксперт C++
1287 / 1221 / 50
Регистрация: 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
Kuzia domovenok
1891 / 1746 / 118
Регистрация: 25.03.2012
Сообщений: 5,925
Записей в блоге: 1
02.04.2012, 13:49 #45
Ага, а разрабатывая "Тетрис" вы тоже завернёте в него 100500 приватных полей, "на всякий случай", "чтобы случайно всё не испортить". Вместо того, чтобы взять и забыть про ООП на время разработки простой программы.

Вопрос стоял о данных, которые вы объявляете приватными, но тут же открываете к ним доступ гетсеттерами.
То, что является интерфейсом класса, должно быть в интерфейсе класса. То, что не является интрфейсом класса, должно не быть функцией в пространстве имён класса.
Ну вот, представьте: разрабатываете вы Тетрис, программу у вас от силы из 5-6 функций. Зачем её усложнять?
В чём отличие в применении
C++
1
void Shape::draw()
От
C++
1
friend void draw(Shape*)
??? Для меня никакой.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.04.2012, 13:49
Привет! Вот еще темы с ответами:

Перегрузка операторов разных класов - C++
здравствуйте уважаемые форумчане начал программировать класс полиномов и начал я перегружать оператор * для разных классов friend...

Можно ли помещать в вектор разные объекты? - C++
у меня разные 3 вида объекта. Но у них есть несколько общих свойств, по которым нужно будет сделать сортировку. Так вот как быть. С...

Перегрузка опереторов для пользовательских класов - C++
#include &lt;iostream&gt; #include &lt;sstream&gt; #include &lt;string&gt; #include &lt;cmath&gt; #include &lt;windows.h&gt; using namespace std; ...

Ошибка в коде при использовании класов - C++
#include &lt;iostream&gt; #include &lt;fstream&gt; #include &lt;time.h&gt; #include &lt;stdio.h&gt; using namespace std; class Hello { int money,...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
02.04.2012, 13:49
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru