Может ли быть два публичных раздела в классе? Если да, то почему? И при каких обстоятельствах мы это делаем?

Меня что-то беспокоит в классах. Например

class A
{
public:
  A()
  {
  .....
  .....
  }

  void cleanup()
  {
  ....
  ....
  ....
  }

public:
  UINT a;
  ULONG b;
};

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


person Abhineet    schedule 27.04.2010    source источник
comment
В вашем классе есть только один общедоступный раздел (плюс ненужный дополнительный спецификатор public в середине).   -  person sbi    schedule 27.04.2010


Ответы (6)


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

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

person Marcelo Cantos    schedule 27.04.2010
comment
+1 Неопределенное расположение элементов в разных метках спецификаторов доступа является важной деталью. - person David Rodríguez - dribeas; 27.04.2010
comment
Я заинтригован. gcc жалуется, когда в списке инициализаторов два атрибута инициализируются в порядке, обратном тому, как они объявлены, это влияет? - person Matthieu M.; 27.04.2010
comment
Он жалуется, потому что атрибуты инициализируются в том порядке, в котором они появляются в объявлении класса (хотя я не понимаю, как это работает с квалификаторами доступа). Может ввести в заблуждение, если в списке инициализаторов они расположены в другом порядке. - person Marcelo Cantos; 28.04.2010
comment
Если у вас есть что-то личное, которое зависит от чего-то публичного, и что-то публичное, что зависит от чего-то частного, то имеет смысл иметь повторяющиеся разделы. Это может произойти, когда у вас много определений типов и перечислений. - person Brian Gordon; 17.09.2013

Как говорит Марсело, вы можете использовать квалификаторы public, private и protected столько раз, сколько пожелаете. «Когда» — это сугубо личное. Некоторым нравится это:

class AClass
{
public:
   // all the public stuff
protected:
   // all the protected stuff
private:
   // all the private stuff
};

но лично (и это действительно просто личное предпочтение) мне нравится делать это:

class AClass
{
   // constructors and destructors
public:
   // public cons/dest
protected:
   // protected cons/dest
private:
   // private cons/dest

   // accessors
public:
protected:
private:

   // methods
public:
protected:
private:

   // members
public:
protected:
private:
};

Не стесняйтесь придумывать свой собственный стиль, который вам удобен. Нет правильного или неправильного способа сделать это. Просто постарайтесь быть последовательным.

person Skizz    schedule 27.04.2010

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

person AndersK    schedule 27.04.2010

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

Обычно так: public/protected/private, в таком порядке, потому что это упрощает жизнь читателям.

  • Люди, использующие этот класс, могут перестать читать, как только дойдут до тега protected, все, что после этого, их не касается.
  • Люди, производные от класса, могут перестать читать, как только дойдут до тега private, все, что после него, является деталями реализации.

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

Однако есть пара хитростей:

  • при использовании программирования меташаблонов вам может потребоваться сначала объявить типы, а затем методы, поэтому вы получите 2 серии public/protected/private
  • при использовании идиомы Key (вместо friend) у вас есть раздел public, который на самом деле предназначен только для небольшой части пользователей и лучше всего изолирован либо в нижней части обычного раздела public, либо после раздела protected.

Наконец, что касается вопроса layout среди атрибутов. Инкапсуляция означает, что атрибуты должны быть private. Итак, либо у вас есть struct и все public, либо у вас есть класс и все private, смешивание двух означает нарушение инкапсуляции, и это ошибка в процессе создания.

person Matthieu M.    schedule 27.04.2010

Класс правильный, public — это просто квалификатор доступа, который будет применяться до тех пор, пока не будет виден следующий квалификатор или конец объявления класса. Нет ограничений на количество этих квалификаторов доступа (общедоступных, частных, защищенных), которые вы можете иметь в классе. Что касается того, почему это полезно, это помогает писать объявления классов так, как вы хотите. Например, я мог бы захотеть, чтобы все функции-члены (общедоступные, защищенные или частные) были объявлены перед (скажем) закрытыми элементами данных.

person Jasmeet    schedule 27.04.2010

Как @Marcelo Cantos answer объясняет, что это разрешено. При самостоятельном написании кода этого следует избегать, так как это приводит только к путанице, когда другие читают ваш код. Единственное место, где я когда-либо видел это в реальной жизни, — это код, сгенерированный различными MFC-мастерами. Всякий раз, когда вы добавляете что-то в свой класс с помощью мастера, он просто добавляет дополнительный раздел в конец вашего класса.

person Björn Pollex    schedule 27.04.2010