В настоящее время я думаю о том, что предпочтительнее использовать имена с именами или именами статических констант. Какой должен быть выбор по умолчанию и почему?
Вариант 1:
namespace Direction
{
enum Direction
{
north,
east,
south,
west,
};
}
Вариант 2:
namespace Direction
{
static const unsigned char north = 0;
static const unsigned char east = 1;
static const unsigned char south = 2;
static const unsigned char west = 3;
}
Оба имеют свои преимущества и недостатки.
Pro enum:
-
некоторые типы безопасности:
void foo(Direction dir); // the compiler won't allow you to just pass an int or a value of an unrelated enum without explicitly casting it
Contra перечисление:
- Безопасность
-
довольно ограничена:
enum A { Entry1 = 1 }; enum B { Entry2 = 10 }; A a; if(a == Entry2) ; // ouch!
-
нет поддержки для любого другого типа, кроме int - до С++ 11 нельзя просто перечислить, например, long long, short или char
-
пространство имен для перечислений субоптимально
-
если не перевернуть перечисление в отдельное пространство имен, тогда все его члены будут загрязнять окружающее пространство имен.
-
если вы переносите enum в отдельное пространство имен, тогда возникает некоторая избыточность при использовании самого перечисления как типа: Затем нужно объявить переменную направления в способе Direction:: Direction (если не использовать "Direction:: Direction", что позволит им снова загрязнить внешнее пространство имен (наконец, в той части кода, где использование директива вступает в силу)), чтобы получить возможность пространства имен своих членов в пути Direction:: north вместо северного
-
Pro static const:
- поддержка более высокого типа в С++ до С++ 11 - можно использовать, например, unsigned char для констант
- правильное определение области - отсутствие загрязнения внешнего пространства имен, без явного запроса его с помощью директивы using (и даже тогда только в ограниченном объеме)
Contra static const:
-
даже меньше безопасности типа, чем перечисления - один больше не может объявить прототип функции следующим образом:
void foo(Direction dir);
но нужно будет сделать это следующим образом:
void foo(unsigned char dir); // now each variable of type unsigned char or of a type that can implicitly be casted into unsigned char can be passed, even if its totally unrelated to the expected "enumeration" or if the value does not match the value of any of the expected consts
EDIT: Здесь я нашел интересную статью об ограничении в типе безопасности перечислений: http://www.drdobbs.com/enumerations/184401797