LINUX.ORG.RU

C++ codestyle: когда использовать `struct`

 , ,


2

2

Касательно code style. Не холивара (struct vs class) ради.

Веду парочку pet-проектов, придерживаюсь одинакового code style в них. Причем, сам code style в процессе разработки изменяется (как я считаю нужным). Сейчас вот задумался над такими пунктами:

  1. struct keyword should be used for types which do not have access specifiers (i.e. all members are public)
  2. struct keyword can also be used for data straightforward objects that provide merely getters and setters
  3. Implicit private section of class should not be used. I.e. the private access specifier should be used explicitly

А почему создал данную тему – я не уверен что написать в ‘‘rationale’’ для данных правил. Т.е. выгдядит, как вкусовщина.

Помогите придать смысла или отказаться от них.

Ответ на: комментарий от anonymous

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

void function(T arg)
{
  if (arg.isFoo())
  {
    doFooThing();
  }
  else if (arg.isBar())
  {
    doBarThing();
  }
}
void function(T arg) {
  if (arg.isFoo()) {
    doFooThing();
  } else if (arg.isBar()) {
    doBarThing();
  }
}
KennyMinigun ★★★★★ ()
Последнее исправление: KennyMinigun (всего исправлений: 1)

Зачем городить ещё один coding style? Выбери один из популярных типа Google и дополни его особенностями проекта. Надеюсь однажды комитет C++ догадается включить в стандарт рекоммендуемый для всех code style как во всех нормальных языках, а проверка его соблюдения будет встроена в компиляторы.

snizovtsev ★★★ ()

«Смысл» - это правила сочетания. Эти правила или постулируются, или выводятся из предыдущих постулатов. В роли выводимых правил может быть статистика. Берешь все свои или не свои юношеские произведения искусства, анализируешь старческим закостенелым творческим умом и пишешь талмут из постулирумых догм.

anonymous ()
Ответ на: комментарий от anonymous

Хорошо сказано. Но я хочу не свод правил «потому, что я так хочу». Я хочу минимальный свод правил, выполняя которые получаешь некие полезности соизмеримые с ограничениями, которые такие правила налагают.

KennyMinigun ★★★★★ ()

По прямому предназначению, объединению родственных данных

struct mouse
{
   int x;
   int y;
   int button;
   size_t timestap;
   void(*callback)(void*data);
};
Для реализации всяких своих типов липа list
struct list
{
  void * data;
  struct list * next;
}ж
Тоесть для конструирования того что надо по мере необходимости,просто из принципа отказываться от этого, зачем? Это просто контейнер как бы для чего угодно.

Deleted ()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от snizovtsev

Зачем городить ещё один coding style? Выбери один из популярных типа Google и дополни его особенностями проекта.

Руководствуюсь собственно правилами Google и Cpp Core Guidelines.

Исключая сильно рестриктивные пункты и пункты типа ‘‘потому, что мы так решили’’

KennyMinigun ★★★★★ ()
Последнее исправление: KennyMinigun (всего исправлений: 1)

А почему создал данную тему – я не уверен что написать в ‘‘rationale’’ для данных правил. Т.е. выгдядит, как вкусовщина.

Если использовать struct только для чистых данных, то экономишь на одном слове «public:» и подсказываешь читателю что обьект пассивен - не имеет поведения и предназначен только для чтения и записи полей

vertexua ★★★☆☆ ()
Последнее исправление: vertexua (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

и пункты типа ‘‘потому, что мы так решили’’

Это тоже неплохо, после привыкания ускоряет чтение и написание кода. Не тратишь время на размышления и угадывание

vertexua ★★★☆☆ ()
Ответ на: комментарий от KennyMinigun

{ на отдельной строке для функций визуально отделает их от их содержимого.

А использую struct для чего-то простого, что само почти ничего не делает, а обрабатывается чем-то другим. Может содержать какие-нибудь утилитарные функции, но по сути такие объекты нужны лишь ради хранения данных.

xaizek ★★★★★ ()
Ответ на: комментарий от KennyMinigun

Отдельно эти 3 пункта не имеют (выводимого) смысла. Нужны основные постулаты: что есть так называемый struct, class. Желательно непротиворечивый набор постулатов. Иначе этими правилами можно будет объяснить все что угодно юношеской незакостенвшей творческой душе.
Взгляд со стороны, не стоит оно того, если занимаешься творческой деятельностью. Разве что, если ты занимаешься техподдержкой, багфиксингом уже достаточно стабильно работающего продукта. Вопрос: зачем ломать, то что уже работает?

anonymous ()
Ответ на: комментарий от snizovtsev

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

Надеюсь никогда, т.к. не хочу парашный снаке_казе.

d_a ★★★★★ ()
Ответ на: комментарий от anonymous

Взгляд со стороны, не стоит оно того, если занимаешься творческой деятельностью.

А может и правда. Само придет (если все же). Просто стараюсь организовывать вещи. Причем не стараюсь давать перфекционизму переходить в прокрастинацию (что сложнее).

KennyMinigun ★★★★★ ()
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

А может и правда. Само придет.

Вроде у физиков есть «принцип минимального действия». Зачем тебе придумывать и да еще соблюдать эти правила. Пользуйся тем, что есть (или насильно навязывают, как во всяких разных гуглах с отступами в питоне).

anonymous ()
Ответ на: комментарий от RazrFalcon

Текст стандарта может помочь (а может и не помочь), когда тебя посадят портировать тонну кода на какой-нибудь косой msvc. И балансируя на грани не компилируется/не работает ты будешь очень рад любой ясности. А для того чтобы пилить новый код на фреймворке (культи), где плюсы по сути вообще не требуются, это разумеется не нужно, там каждый первый такой умвр-щик.

d_a ★★★★★ ()

struct и class отличаются только тем что публично, а что приватно, ну и особенности наследования. Следовательно, юзать надо то, что требуется в конкретном случае. Больше разницы нет.

peregrine ★★★★★ ()

Моё ИМХО примерно такое - если у тебя сущность только хранит данные, не имеет внутреннего состояния и методов - тогда struct. Во всех остальных случаях - class.

Dark_SavanT ★★★★★ ()

Из C++ Core Guidelines от Страуструпа:

C.1: Organize related data into structures (structs or classes)
C.2: Use class if the class has an invariant; use struct if the data members can vary independently
C.8: Use class rather than struct if any member is non-public

Короче говоря, struct для POD

Rot1 ()
Ответ на: комментарий от Rot1

Вопрос: если в процессе развития проекта я захочу добавить функции или приватные поля в структуру, то что делать? Переименовывать в класс?

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

anonymous ()
Ответ на: комментарий от Dark_SavanT

если у тебя сущность только хранит данные, не имеет внутреннего состояния и методов - тогда struct.

Почему и зачем, если можно класс и в этом случае, для единообразия? Вкусовщина.

Einstok_Fair ★★ ()
Ответ на: комментарий от Einstok_Fair

struct в данном случае только способ быстро понять что за сущность перед тобой. если struct, то как сказали выше, это POD, если class - то всё по взрослому.

Вкусовщина, да.

Dark_SavanT ★★★★★ ()
Ответ на: комментарий от anonymous

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

Rot1 ()
Ответ на: комментарий от Rot1

Это я был, если что.

Вот смотри, случай из реального проекта, - есть структура для кривых Безье. Я захотел для удобства добавить в структуру функцию float length() const, которая вычисляет длину кривой. Делать ее свободной float bezierLength(const bezierCurve &bc) не хочу - это будет лишнее засорение глобального неймспейса. Потом подумал, что в общем-то хорошо бы кэшировать ее, так как какая-то кривая один раз создается, а потом length используется много раз для отрисовки, и добавил приватное поле mutable float m_cachedLength для ленивой инициализации. Понимаю, что получается уродство - структура с приватным полем, но как исправить не знаю.

На каком этапе я пошел не туда? Твои идеи как сделать лучше?

ncuxer ()
Последнее исправление: ncuxer (всего исправлений: 2)
Ответ на: комментарий от ncuxer

Ну и забыл добавить - т.к. появляется кэш, то вводятся сеттеры-геттеры, чтобы кэшированное значение сбрасывалось в случае изменения кривой. Соответсвенно struct меняется на class. Для меня это выглядит как эволюцией кода, а не говнокодом

ncuxer ()
Последнее исправление: ncuxer (всего исправлений: 1)