Обоснование семантики доступа enum в C ++ - PullRequest
2 голосов
/ 22 марта 2012

Может ли кто-нибудь пролить свет на семантику для доступа к перечислению, определенному в классе в 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 в семантике доступа был бы лучшим вариантом ... Я хотел бы представить имя class . необязательный параметр, который сохраняет совместимость с Си.

Ответы [ 2 ]

6 голосов
/ 22 марта 2012

В C ++ 03, как и в C, enum не вводит новую область видимости.Определенные имена входят в окружающую область.Это может быть пространство имен или класс.

C ++ 11 добавил перечисленные области и перечисления на основе.

Обычный C ++ 03 enum:

enum Cpp03 { a, b, c };

C ++ 11 based enum:

enum Cpp11Based: long { a, b, c };

C ++ 11 scoped 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.

Я предполагаю, что вы столкнулись с расширением языка.

1 голос
/ 22 марта 2012

Основной ответ заключается в том, что ваше "Учитывая, что enum является контейнером / областью действия", является просто неправильным - согласно C и C ++, enum не не устанавливает область действия (и не является контейнером.)

Короче говоря, enum whatever { a, b, c};

не сильно отличается от:

const int a = 0;
const int b = 1;
const int c = 2;

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

...