2012-03-09 4 views
13

Должны ли вы объявлять перечисления внутри или вне класса, если указанные перечисления используются только в функциях класса?Должны ли вы объявлять перечисления внутри или вне класса?

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 
+7

Как и во всех вопросах [в стиле кодирования], ответ «это зависит». –

+2

У кого-то может быть немного больше информации об этом, кроме меня, но моя стратегия всегда заключалась в том, чтобы не выставлять что-то, пока оно не должно быть раскрыто. (Другими словами, если он используется только внутри, то сохраните его внутри.) – Corbin

+0

Как обычно, с вопросами стиля кодирования нет определенного ответа.Загрязнение глобальной области обычно не является хорошей идеей из-за риска противоречивых деклараций, но если вы придерживаетесь своего «собственного» пространства имен, это строго зависит от предпочтений. –

ответ

14

Настоящая цель - не загрязнять область действия (глобальное или пространство имен) и объединять связанные значения вместе (работает с товарами с автозавершением в среде IDE).

С C++ 11, вы можете объявить сильно типизированных перечислений с помощью:

enum class MyEnum { 
    Value0, 
    Value1 
}; 

, которые обязательно использоваться в качестве MyEnum::Value0 (а не Value0).

В C++ 03, вы можете более или менее эмулировать с:

struct MyEnum { 
    enum Type { 
    Value0, 
    Value1 
    }; 
}; 

Но тогда тип перечисления является MyEnum::Type, который немного отличается.

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

+1

-1 «Это предотвращает загрязнение глобальной сферы действия». Нет, это не так, но если это объявление должно быть в глобальном масштабе (что редко приходится), то загрязнение сводится к одному имени (имя типа) вместо нескольких имен (значения перечисления). –

+1

@ Cheersandhth.-Alf: Право, оставшееся от моего мысленного поезда, реальное намерение было выражено во введении * избегайте загрязнения среды (глобального или пространства имен) *. Я бы рекомендовал всегда использовать пространства имен ... ожидать, что скрипт вроде программ (в C++, да!) Редко требует этого. –

+1

ok, удален downvote –

8

Если только члены вашего класса используют enum предпочтительно объявить enum внутри класса.
Это предотвращает имена/глобальное пространство от загрязнения из-за ненужные имена символов & также
Это более intutive для пользователей класса, это помогает пользователю знать, что enum будет использоваться только классом.

Общее правило, которое вы должны выполнить следующие действия:
Не добавляйте символ в области видимости (глобальный/имен), который не будет доступ (&, следовательно, не требуется) в этой области.

+0

-1 глобальное пространство имен не является единственной альтернативой объявлению в классе. –

+0

@ Cheersandhth.-Alf: ответ не говорит, что глобальное пространство имен является альтернативой декларации класса, оно просто говорит, почему это не очень хорошая идея в этом случае. Я немного растерялся относительно того, что вы делаете для этого. –

+0

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

0

As Matthieu M. упомянутый, в C++ 11 использовать Strongly typed enumerations.

Хороший способ имитировать их в C++ 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 
+0

-1 «лучше, потому что» должно быть «я предпочитаю, потому что». Например, я предпочитаю обертывание в structs, потому что структуры могут быть напечатаны внутри классов (вы не можете «использовать пространство имен» внутри класса). То, как я написал, теперь все в порядке, но если я заявляю, что мое предпочтение «лучше», чем чужое предпочтение, тогда это было бы бессмысленным или просто неправильным утверждением. –

+0

Как сказал Альф, я предпочитаю использовать structs для способности typedef. Размещение функций в пространстве имен, в котором содержится структура, содержащая перечисление, достаточна для того, чтобы ADL мог вступить. –

+0

@Alf: 'typedef' и' using namespace' делают разные вещи, поэтому непонятно, почему вы их сравнили, вам может понравиться для разработки. Я написал «лучше» и объяснил, как это сделать. –

0

Это зависит. Стремитесь минимизировать воздействие деталей реализации. Например. заключать вещи в пространствах имен и/или классы и/или отдельно скомпилированные файлы реализации. И, как мы надеемся, очень ясно, глобальное пространство имен и класс в целом - это совсем не единственные варианты. Я., объявление чего-то не в классе - это не единственный способ свести к минимуму воздействие (каковы некоторые другие способы? --- о, ну, помните третье предложение этого ответа).

Смежные вопросы