Перечисления: Могут ли они сделать .h или должны оставаться в .cpp?

Если у меня есть что-то вроде:

enum
{
    kCP_AboutBox_IconViewID = 1,
    kCP_AboutBox_AppNameViewID = 2,
    kCP_AboutBox_VersionViewID = 3,
    kCP_AboutBox_DescriptionViewID = 4,
    kCP_AboutBox_CopyrightViewID = 5
};

в моем .cpp может ли он пойти в .h?

Более того, какие другие менее известные вещи вы можете добавить в .h помимо определений классов, переменных и т.д. и т.д.

Ответы

Ответ 1

Файл .h - это, по сути, просто код, который во время компиляции помещается над любым .cpp(или файлом .h, если на то пошло), в который он входит. Поэтому вы можете просто поместить любой код из файла .cpp в .h и он должен скомпилировать штраф.

Однако это важная конструкция. Ваш код (например, перечисление) ДОЛЖЕН быть помещен в файл .h, если вам нужно выставить его на код, который вы включаете .h файл. Однако, если перечисление относится только к коду в вашей реализации .cpp заголовка, вы должны инкапсулировать его только в файле .cpp.

Ответ 2

Не забудьте использовать заголовок include guard в заголовках, например:

#ifndef header_name_h
#define header_name_h
...
#endif

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

Кроме того, никогда не было:

using namespace <name>;

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

Ответ 3

Да, определение вашего перечисления может находиться в файле заголовка (.h). Однако не повторяйте определение в вашем файле .cpp.

Ответ 4

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

Ответ 5

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

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

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

NamespaceOrClass::EnumValue

Кроме того, в качестве sidenote перечисления автоматически перебирают значения из первой, которую вы даете (или 0).

enum
{
    kCP_AboutBox_IconViewID = 1,
    kCP_AboutBox_AppNameViewID = 2,
    kCP_AboutBox_VersionViewID = 3,
    kCP_AboutBox_DescriptionViewID = 4,
    kCP_AboutBox_CopyrightViewID = 5
};

Точно так же, как

enum
{
    kCP_AboutBox_IconViewID = 1,
    kCP_AboutBox_AppNameViewID,
    kCP_AboutBox_VersionViewID,
    kCP_AboutBox_DescriptionViewID,
    kCP_AboutBox_CopyrightViewID
};

Это не проблема или ошибка, просто стилистическая на самом деле.

Ответ 6

Одно правило определения допускает это при 3.2/5. Все перечисленные ниже могут быть помещены в заголовки и включаться несколько раз в разные единицы перевода.

Может быть более одного определения типа класса (раздел 9), тип перечисления (7.2), встроенная функция с внешней связью (7.1.2), шаблон класса (раздел 14), нестатический шаблон функции (14.5.5), статический член данных шаблона класса (14.5.1.3), функция-член шаблона класса (14.5.1.1) или специализированная специализация шаблона, для которой не заданы некоторые параметры шаблона (14.7, 14.5.4) в программе, при условии, что каждое определение появляется в другом блоке перевода, и при условии, что определения удовлетворяют следующим требованиям.

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

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

Ответ 7

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