Как я должен заказать членов класса C ++? - PullRequest
54 голосов
/ 21 ноября 2008

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

Ответы [ 15 ]

48 голосов
/ 21 ноября 2008

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

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

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

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

37 голосов
/ 21 ноября 2008

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

Мэтью Уилсон (требуется подписка на Safari) рекомендует следующий порядок: «Построение, Операции, Атрибуты, Итерация, Состояние, Реализация, Члены и мой любимый, Не подлежит реализации».

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

8 голосов
/ 21 ноября 2008

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

5 голосов
/ 21 ноября 2008

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

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

Есть несколько исключений.

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

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

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

Но речь идет не о заказе по доступу, а о по интересу к потребителю .

4 голосов
/ 21 ноября 2008

Я обычно определяю сначала интерфейс (для чтения), который является общедоступным, затем защищенным, затем личным. Теперь во многих случаях я делаю шаг вперед и (если смогу с этим справиться) использую шаблон 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 имеет внутренний класс, для которого внешний мир даже не видит операций. Это сохраняет интерфейс класса полностью чистым: доступен только реальный интерфейс. Не нужно спорить о порядке.

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

3 голосов
/ 06 мая 2017

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

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

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

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

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

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

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

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

2 голосов
/ 16 марта 2009

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

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

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

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

2 голосов
/ 21 ноября 2008

Я склонен следовать Руководству по стилю кодирования POCO C ++ .

2 голосов
/ 21 ноября 2008

Я думаю, что это все о читабельности.

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

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

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

1 голос
/ 16 марта 2009

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

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

...