Должны ли вы объявлять перечисления внутри или вне класса?
Должны ли вы объявлять перечисления внутри или вне класса, если указанные перечисления используются только в функциях членов класса?
namespace nspace
{
// need to append OC, as this pollutes the current namespace
enum OUTSIDE_CLASS {OC_POINTS, OC_LINES, OC_LINE_LOOP, :::};
enum OTHER_ENUM {OE_POINTS};
class VertexBuffer
{
public:
enum INSIDE_CLASS {POINTS, LINES, LINE_LOOP, :::};
void foo(OUTSIDE_CLASS e);
void bar(INSIDE_CLASS e);
}
};
// usage
nspace::VertexBuffer v;
v.foo(nspae::VB_POINTS);
v.bar(nspace::VertexBuffer::POINTS); // more pedantic
Ответы
Ответ 1
Реальная цель состоит в том, чтобы не загрязнять область (глобальное или пространство имен) и группировать связанные между собой значения вместе (работает с товарами с автозавершением в среде IDE).
С С++ 11 вы можете объявить строго типизированные перечисления, используя:
enum class MyEnum {
Value0,
Value1
};
которые обязательно вызываются как MyEnum::Value0
(а не Value0
).
В С++ 03 вы можете более или менее эмулировать это с помощью:
struct MyEnum {
enum Type {
Value0,
Value1
};
};
Но тогда тип перечисления MyEnum::Type
, который является немного отличающимся.
Ленивый вариант состоит в том, чтобы просто сбрасывать его в классе, но я все же предпочитаю вложенное перечисление с областью, даже внутри класса, просто чтобы было ясно, что эти значения не потеряны, а вместо этого взаимосвязаны.
Ответ 2
Если только члены вашего класса используют enum
, желательно объявить enum
внутри класса.
Это предотвращает загрязнение пространства имен/глобального пространства из-за ненужных имен символов, а также
Он более интуитивен для пользователей этого класса, он помогает пользователю узнать, что enum
будет использоваться только классом.
Следующее общее правило:
Не добавляйте символ в область (глобальное/пространство имен), к которой не будет доступ (и, следовательно, не требуется) в этой области.
Ответ 3
Как упоминал Маттиу М., в С++ 11 используйте Сильно типизированные перечисления.
Хороший способ имитировать их в С++ 03 - это перенос перечислений в пространства имен. Это лучше, чем обертывание в struct
, потому что это пространство имен может иметь функции, которые можно найти, используя зависящий от аргумента поиск имени. Например:.
namespace MyEnum {
enum Type {
Value0,
Value1
};
std::ostream& operator<<(std::ostream&, Type);
std::istream& operator>>(std::istream&, Type&);
}
MyEnum::Type value;
std::cout << value; // uses the overload from MyEnum
std::cin >> value; // uses the overload from MyEnum
Ответ 4
Это зависит. Стремитесь минимизировать воздействие деталей реализации. Например. заключать вещи в пространствах имен и/или классы и/или отдельно скомпилированные файлы реализации. И, как мы надеемся, очень ясно, глобальное пространство имен и класс в целом - это совсем не единственные варианты. Я., объявляя что-то в классе, не единственный способ свести к минимуму воздействие (каковы некоторые другие способы? --- о, ну, помните третье предложение этого ответа).