Обоснование семантики доступа enum в C++
Может кто-нибудь пролить свет на семантику для доступа к перечислению, определенному в классе в C++?
В частности, почему члены перечисления доступны по имени класса, а не по самому перечислению? Учитывая, что enum
это контейнер / область, так же, как namespace
а также class
почему доступ к элементу контейнера обрабатывается по-разному, когда это enum
чем когда это class
?
Дано
namespace mynamespace
{
class myclass
{
public:
enum myenum
{
enum1,
enum2
};
int myint;
};
}
Почему полное название для enum1
mynamespace::myclass::enum1
и не mynamespace::myclass::myenum::enum1
?
Хотя последний "работает", это не "рекомендуемый" способ вызова, и некоторые компиляторы выдают там предупреждение. ИМХО, оно должно быть не только правильным, но и единственным способом доступа к нему.
Это делает для действительно странных правил доступа, и делает вещи очень странными, когда вы добавляете новый enum1
в другом перечислении (в этот момент вы должны добавить классификатор).
Действительно, это побеждает цель перечисления. Члены enum действительно больше членов класса, чем enum, и я должен сказать, что считаю поведение в других языках (например, C#) гораздо более предпочтительным.
Я предполагаю, что это для обеспечения совместимости с C, но я не понимаю, почему лучше было бы указывать имя enum в семантике доступа... Я думаю, что сделать имя класса необязательным было бы вариантом, сохраняющим совместимость с C,
2 ответа
В C++03, как и в C, enum
не вводит новую сферу. Определенные имена входят в окружающую область. Который может быть пространством имен или классом.
В C++11 добавлены перечисления с областями видимости и перечисления на основе.
Обычный C++ 03 enum
:
enum Cpp03 { a, b, c };
На основе C++11 enum
:
enum Cpp11Based: long { a, b, c };
C++11 область применения enum
(который действует как область имен, как в вашем примере):
enum class Cpp11Scoped1 { a, b, c };
enum struct Cpp11Scoped2 { a, b, c };
Последние две формы эквивалентны и позволяют писать, например, Cpp11Scoped1::a
,
Наконец, область действия enum
может быть основан (указав базовый тип для имен, то есть размер и подпись):
enum class Cpp11ScopedAndBased: long { a, b, c };
Некоторые компиляторы C++03, включая Visual C++, обеспечивали функциональность области видимости и для обычного C++ 03 enum
,
Я предполагаю, что то, с чем вы столкнулись, это расширение языка.
Основной ответ заключается в том, что ваш "Учитывая, что enum
является контейнером / областью видимости "просто неправильно - согласно C и C++, enum
не устанавливает область действия (и не является контейнером).
Короче, enum whatever { a, b, c};
не сильно отличается от:
const int a = 0;
const int b = 1;
const int c = 2;
Пока вы можете использовать enum whatever
чтобы определить переменные, которые могут содержать значения этого типа, они, как правило, не сильно отличаются от некоторого целочисленного типа, способного содержать правильный диапазон значений.