Подтвердить что ты не робот

Как я должен упорядочить членов класса С++?

Лучше ли иметь всех частных членов, затем всех защищенных, а затем всех публичных? Или наоборот? Или должно быть несколько частных, защищенных и общедоступных ярлыков, чтобы операции можно было отделить от конструкторов и т.д.? Какие вопросы следует принимать во внимание при принятии этого решения?

4b9b3361

Ответ 1

Сначала я поставил публичный интерфейс, но я не всегда делал это. Раньше я делал что-то позади, с закрытыми, затем защищенными, а затем публичными. Оглядываясь назад, это не имело большого смысла.

Как разработчик класса, вы, вероятно, будете хорошо знакомы с его "внутренностями", но пользователи этого класса не особо заботятся, или, по крайней мере, не должны. Они в основном заинтересованы в том, что класс может сделать для них, не так ли?

Поэтому я сначала ставил публику и организовывал его, как правило, с помощью функции/утилиты. Я не хочу, чтобы им приходилось пробираться через мой интерфейс, чтобы найти все методы, связанные с X, я хочу, чтобы они видели все это вместе организованным образом.

Я никогда не использую несколько разделов public/protected/private - слишком запутанным, чтобы следовать по моему мнению.

Ответ 2

Google одобряет этот порядок: "Typedefs и Enums, Constants, Constructors, Destructor, Methods, включая статические методы, члены данных, включая статические данных".

Matthew Wilson (требуется подписка на Safari) рекомендует следующий порядок: "Строительство, операции, атрибуты, итерация, состояние, реализация, участники, и мой любимый, Не быть реализованным".

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

Ответ 3

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

Ответ 4

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

class Example1 {
public:
   void publicOperation();
private:
   void privateOperation1_();
   void privateOperation2_();

   Type1 data1_;
   Type2 data2_;
};
// example 2 header:
class Example2 {
   class Impl;
public:
   void publicOperation();
private:
   std::auto_ptr<Example2Impl> impl_;
};
// example2 cpp:
class Example2::Impl
{
public:
   void privateOperation1();
   void privateOperation2();
private: // or public if Example2 needs access, or private + friendship:
   Type1 data1_;
   Type2 data2_;
};

Вы можете заметить, что я постфиксные частные (а также защищенные) элементы имеют знак подчеркивания. Версия PIMPL имеет внутренний класс, для которого внешний мир даже не видит операции. Это полностью очищает интерфейс класса: открыт только реальный интерфейс. Не нужно спорить о порядке.

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

Ответ 5

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

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

Есть некоторые исключения.

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

Но это относительно редкие ситуации.

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

Но это меньше о упорядочении по доступу и более упорядоченности по интересам для потребителя.

Ответ 6

Я все думаю о читаемости.

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

В целом, я чувствую, что самые важные вещи должны быть первыми. Для 99,6% всех классов, грубо говоря, это означает публичные методы, и особенно конструктор. Затем появляются публичные элементы данных, если они есть (помните: инкапсуляция - хорошая идея), за которыми следуют любые защищенные и/или частные методы и члены данных.

Это материал, который может быть покрыт стандартами кодирования больших проектов, может быть хорошей проверкой.

Ответ 8

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

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

Ответ 9

Обратите внимание, что (в зависимости от вашего компилятора и динамического компоновщика) вы можете сохранять совместимость с предыдущими версиями разделяемой библиотеки, добавляя только к концу класса (то есть к концу интерфейса), а не удаляя или изменяя что-нибудь еще. (Это верно для g++ и libtool, и эта схема управления версиями для разделяемых библиотек GNU/Linux отражает это.)

Также существует идея, что вы должны заказывать членов класса, чтобы избежать потраченного впустую пространства из-за выравнивания памяти; одна стратегия состоит в том, чтобы заказать членов от минимального до самого большого размера. Я никогда не делал этого ни на С++, ни на C.

Ответ 10

На практике это редко имеет значение. Это прежде всего вопрос личных предпочтений.

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

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

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

Ответ 11

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

class Foo
{
private:
  int bar;

public:
  int GetBar() const
  {
    return bar;
  }
};

Здесь элемент bar помещается перед элементом GetBar(), поскольку последний используется последним. Это может привести к нескольким разделам доступа, как в следующем примере:

class Foo
{
public:
  typedef int bar_type;

private:
  bar_type bar;

public:
  bar_type GetBar() const
  {
    return bar;
  }
};

Элемент bar_type используется членом bar, см.?

Почему это? Я не знаю, казалось бы более естественным, что если вы встретите кого-то из участников в реализации, и вам понадобится дополнительная информация об этом (и IntelliSense снова прикручен), вы можете найти его где-то выше, откуда вы работаете.

Ответ 12

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

В этом случае наиболее предпочтительными являются типы-члены и константы, за которыми следуют операторы построения, операции и затем переменные-члены.

Ответ 13

Стиль кодирования является источником для неожиданно нагретого разговора, поэтому я рискую дать другое мнение:

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

Отклонение - это то, что мы делаем.

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

Однако для тех, кому требуется понимать код, во время просмотра кода, запроса на перенос или обслуживания, порядок имеет большое значение - правило прост:

элементы должны быть определены до их использования

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

Создание разделения строго на частных v.s. public нарушает это правило, потому что частные члены класса появятся после того, как они были использованы в любом общедоступном методе.

Ответ 14

Сначала введите частные поля.

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

Они просто используют intellisence (или браузер классов) для этого.

Если кто-то читает определение класса, это обычно потому, что они хотят понять, как это работает.

В этом случае знание полей помогает больше всего. Он сообщает вам, что представляют собой части объекта.

Ответ 15

В зависимости от ваших предпочтений. Нет "правильного пути".

Когда я делаю С++ в своих собственных проектах для домашних животных, я лично придерживаюсь соглашения о том, что я добавляю модификатор доступа перед каждым объявлением участника или метода.