Приветики
После некоторых занятий на белке и ответов в rsdn на тему других языков я решил написать немного своих размышлений про мой любимы си++
Чем отличается структура от класса — мы знаем.
Это по сути казалось бы одно и тоже, вот только в struct изначально доступ к мемберам public, а в class — private
Тему наследования пока опустим для упрощения.
Я одно время ленился выбирать что писать class или struct в том или ином конкретном случае, и тупо начал писать везде struct в своём коде.
Думал мне так проще. Даже бывало делал всё public.
Бывает хочется скрыть data member от внешнего изменения. Для readonly доступа приходится писать get метод.
Таких свойств для скрытия когда становится много — то для каждого писать свой геттер — рутина.
Как быть?
Объединяем скрытые мемберы по смыслу в общую структуру. Не делаем в ней виртуальных методов, а главное доступ весь public в этой структуре.
Теперь добавляем в исходный класс одно свойство, чтобы поместить его в private / protected секцию.
На всё это свойство достаточно одного метода геттера, выдающего данные по константной ссылке.
В процессе разработки бывает что класс разрастается и не вмещается в экран.
Такой подход разделения на части призван повысить читабельность исходников.
(а не только уменшить кол-во геттеров при скрытии)
Про friend declaration ещё хотелось бы упомянуть.
Вот не нравится мне писать friend в си++ для предоставления доступа к мемберам.
А зачем это вообще нужно? Например когда передаём this всего класса во внешнюю функцию.
Так же проще, взял да написал friend. А как иначе?
Не полениться бы и порассуждать логически.
Если внешней функции нужны скрытые параметры класса, то можно их туда передать пачкой (вместо this / отдельно от this).
Для этого вообще не нужно писать friend declaration.
Более того можно передать по константной ссылке в случае readonly доступа — через метод data(), или для полного доступа — просто m_data.
Подытожу мысль.
class — для сокрытия и для виртуальности.
struct — это просто набор свойств.
Получилось подобие мини article, а не впорос.
--
Случаи с наследованием тоже бы рассмотреть в таком ключе, по которому реплаи прошу постить отдельно от реплаев на article выше.
Как вы относитесь к наследованию у struct, или используете в нём только инкапсуляцию?
Тот же вопрос: в class -ах наследование используете?
Наследование методов от базы не всегда есть хорошо.
Есть ли способ запретить в потомке вызов из public для отдельного метода из базы?
Например оператор копирующего присваивания в базе.
* Но чтобы некоторые остальные методы из базы остались как public
Здравствуйте, Sm0ke, Вы писали:
S>Чем отличается структура от класса — мы знаем.
Думаю вопрос нужно ставить не чем отличаются структуры и классы в C++, а чем отличаются структуры в Си и структуры в C++. И просветление наступит, когда один и тот же код будет компилироваться как в Си, так и в C++. Только вот Си и C++ не так чтобы совсем уж совместимы. Суть же в парадигмах, то есть стилю мышления программиста.
И у меня вопросы в именовании. Вот например хотим так вынести из строки size и capacity. data уже не назовёшь.
S>Если внешней функции нужны скрытые параметры класса, то можно их туда передать пачкой (вместо this / отдельно от this).
разные случаи бывают. operator== так не сделаешь, ему лишний параметр помешает пролазить в алгоритмы. Писать отдельную лямбду тоже не добавляет простоты. Поддержки каррирования нет. В общем, нет счастья.
Здравствуйте, sergii.p, Вы писали:
SP>Здравствуйте, Sm0ke, Вы писали:
S>>Объединяем скрытые мемберы по смыслу в общую структуру.
SP>мне кажется, получается немного косноязычно. Также смешение функций и обычных членов не выглядит красиво SP>
SP>registrator.data().max_speed
SP>
Можно перегрузить в классе Registrator оператор стрелка ->
Чтобы он возвращал указатель на const Registrator_data
SP>И у меня вопросы в именовании. Вот например хотим так вынести из строки size и capacity. data уже не назовёшь.
Можно назвать как удобно. Не обязательно именно data.
Опять же с оператором стрелка можно обойтись и без метода геттера на выдачу пачки параметров.
S>>Если внешней функции нужны скрытые параметры класса, то можно их туда передать пачкой (вместо this / отдельно от this).
SP>разные случаи бывают. operator== так не сделаешь, ему лишний параметр помешает пролазить в алгоритмы. Писать отдельную лямбду тоже не добавляет простоты. Поддержки каррирования нет. В общем, нет счастья.
Тут сперва решить вопрос что именно нужно сравнить: Весь класс, или отдельно data
Но можно же оба варианта
Если надо сравнить только struct Registrator_data отдельно, есть такая возможность задать операторы сравнения для неё
Тогда для class Ragistrator можно вывести автоматически компилятором operator <=> (/* ... */) = default;
Конечно есть нюансы:
* Когда оператор стрелка уже занят
* Когда в классе есть обычные public свойства, не помещённые в m_data (придётся помнить: когда писать точка / когда стрелка)
Собственно я не призываю всегда делать именно так. Возможно при случае с малым кол-вом геттеров — проще взят их да написать.
Но когда их много, то почему бы и не сгруппировать?
SP>... Поддержки каррирования нет.
А можно пример как вы каррируете?
p/s
короче это всё обходные пути вокруг отсутствия public readonly в плюсах
Здравствуйте, velkin, Вы писали:
V>Здравствуйте, Sm0ke, Вы писали:
S>>Чем отличается структура от класса — мы знаем.
V>Думаю вопрос нужно ставить не чем отличаются структуры и классы в C++, а чем отличаются структуры в Си и структуры в C++. И просветление наступит, когда один и тот же код будет компилироваться как в Си, так и в C++. Только вот Си и C++ не так чтобы совсем уж совместимы. Суть же в парадигмах, то есть стилю мышления программиста.
название темы: Проектирование класса
рассмотрен случай со скрытием свойств класса в private / protected секциях
чтобы не пришлось писать много геттеров
про си я не писал, и смотреть отличия ключевых слов struct от class собственно не конечная цель этого топика
Похоже мне надо уметь лучше формулировать постановку вопроса)
Делее предлагаю рассмотреть случай, когда методов внутри класса добавлено очень много.
Как можно сделать исходник класса более наглядным?
С учётом скрытия и без.
Здравствуйте, Sm0ke, Вы писали:
S>Бывает хочется скрыть data member от внешнего изменения. Для readonly доступа приходится писать get метод. S>Таких свойств для скрытия когда становится много — то для каждого писать свой геттер — рутина.
Может быть, вот в этом самом месте нужно просто остановиться и подумать, а стоит ли в этом случае закрывать доступ к членам? Доступ к данным через геттеры и сеттеры хоть и является распространенным дизайнерским решением, но это решение не является ни единственным, ни догмой. Имхо, не стоит пытаться найти один универсальный подход на все случаи жизни. Структуры с полностью открытыми данными тоже вполне себе вариант и имеют свои преимущества. Важно просто чувствовать, в каком случае, что лучше подходит.
--
Не можешь достичь желаемого — пожелай достигнутого.