typedef'ing enum не делает значения enum видимыми - PullRequest
13 голосов
/ 15 марта 2011

У меня есть класс, в котором у меня есть перечисление, определенное так:

class X
   {
   public:
      enum Direction {DIR_LEFT, DIR_RIGHT};
   };

Теперь я хочу, чтобы это перечисление повторно использовалось в другом классе, например:

class Y
   {
   public:
      typedef X::Direction Direction;
   };

Как и ожидалось, использование Y :: Direction работает правильно, например ::

void myFunction (Y::Direction dir)
{
}

Но значения в перечислении, похоже, не копируются вместе с typedef. Если я напишу следующее, я получу ошибки компиляции:

myFunction (Y::DIR_LEFT);

Вместо этого я должен снова обратиться к исходному месту перечисления, например:

myFunction (X::DIR_LEFT);

Который побеждает мою цель типизации перечисления.

Единственное решение, которое я вижу, это переместить перечисление из класса X и поместить его в другой класс (например, MyEnums), чтобы его можно было повторно использовать X и Y (хотя они все равно должны использовать MyEnums :: DIR_LEFT и MyEnums :: DIR_RIGHT), но, по крайней мере, код больше не зависит от класса X.

Почему сами значения перечисления не отображаются через typedef?

Существуют ли другие шаблоны для управления перечислениями в разных классах?

Ответы [ 5 ]

14 голосов
/ 15 марта 2011

К сожалению, C ++ не вводит новую область видимости с enum, хотя C ++ 0x улучшает вещи.

Практически это означает, что вы не можете набирать enum и получать перечисляемые значения..

То, что вы можете сделать, это использовать вложенную структуру с именем, которое вы хотите для enum и typedef THAT.

class X
{
public:
    struct Direction { enum EnumType {LEFT, RIGHT}; };
};

class Y
{
public:
    typedef X::Direction Direction;
};

Теперь вы можете сделать: myFunction (Y::Direction::LEFT);

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

1 голос
/ 15 марта 2011

Если вы хотите, чтобы значения перечисления были членами обоих классов, решение состоит в том, чтобы определить отдельный класс с перечислением и наследовать его, например:

class MyEnums
{
protected:
    ~MyEnums() {} //  Prevent delete through pointer to this class
public:
    enum Direction
    {
        DIR_LEFT,
        DIR_RIGHT
    };
};

class X : public MyEnums
{
    // ...
};

class Y : public MyEnums
{
    // ...
};

Пользователи увидят X ::Направление, X :: DIR_LEFT и Y :: Направление, Y :: DIR_LEFT.Конечно, они все еще смогут передавать Y :: DIR_LEFT в функцию, ожидающую X :: Direction;чтобы предотвратить это, сделайте MyEnums шаблоном с производным классом в качестве аргумента шаблона.

1 голос
/ 15 марта 2011

Вот мое понимание того, как перечисления работают в C ++. (Или, по крайней мере, мое наблюдаемое поведение перечислений в Microsoft Visual C ++.)

Ключевое слово enum не создает область видимости так же, как классы.

Полное имя для вашего перечисления 'Direction' - X :: Direction. Значения в этом перечислении все еще являются частью области видимости класса, поэтому они являются X :: DIR_LEFT и X :: DIR_RIGHT.

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

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

0 голосов
/ 08 октября 2013

Если исходное объявление:

    class X
    {
    public:
      enum Direction {DIR_LEFT, DIR_RIGHT};
    };

встроено в большую унаследованную кодовую базу, то нам может потребоваться решение, которое не изменяет любые существующие применения X ::Направление.В этом случае довольно уродливо:

    class Y
    {
    public:
       typedef enum X::Direction Direction;
       static const enum X::Direction DIR_LEFT = X:DIR_LEFT;
       static const enum X::Direction DIR_RIGHT = X:DIR_RIGHT;
    }

работает ...

Определенно не рекомендуется для нового кода, однако!

0 голосов
/ 15 марта 2011

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

direction.hpp:

#ifndef DIRECTION_HPP
enum Direction {DIR_LEFT, DIR_RIGHT};
#endif

x.hpp:

#ifndef X_HPP
#include "direction.hpp"

class X
{
  Direction dir;
};
#endif // X_HPP

y.hpp

#ifndef Y_HPP
#include "direction.hpp"

class Y
{
  Direction dir;
};
#endif // Y_HPP
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...