2011-03-15 54 views
13

我有一个类中,我有一个枚举,这样的定义:typedef'ing一个枚举不会使枚举值可见

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

现在我想此枚举在另一个类可以重复使用,像这样:

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

正如预期的那样,使用ÿ::方向正常工作,如:

void myFunction (Y::Direction dir) 
{ 
} 

但ENU内的值meration似乎不会与typedef一起“复制”。如果我写了下面,我得到的编译错误:

myFunction (Y::DIR_LEFT); 

相反,我不得不再次提及原来的地方枚举的,像这样的:

myFunction (X::DIR_LEFT); 

这违背了我的typdefing的目的枚举。

我看到的唯一解决方案是将枚举从类X中移出,并将其放入另一个类(例如MyEnums),以便它可以被X和Y重用(尽管它们仍应该使用MyEnums :: DIR_LEFT并且MyEnums :: DIR_RIGHT),但至少代码不再依赖于类X.

为什么枚举值本身没有通过typedef公开?

是否有任何其他模式来管理不同类中的枚举?

回答

14

不幸的是,C++没有引入一个新的范围,但是enum尽管C++ 0x正在改进。

实际上,这意味着您不能键入一个枚举并获取枚举值。

可以 do是使用一个嵌套的结构与你想要的名称为枚举和typedef THAT。

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

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

现在你可以这样做: myFunction (Y::Direction::LEFT);

嵌套结构的目的是建立一个“假”的范围holld两个枚举名称和它的值。

+3

你可能应该删除'DIR_'前缀,因为它是一个人造的“穷人的命名空间”:'struct Direction {enum {LEFT,RIGHT};};' - 只比C++ 0x语法更脏“枚举类方向{LEFT,RIGHT};' – anatolyg 2011-03-15 18:01:36

+0

@anatolyg事实上,这是一个好主意,我做了这个改变。 – 2011-03-15 18:19:04

0

任何由多于一个类共享的东西都应该在类之外进行分解,也可以放到父类中。

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

你不是现在用你的枚举来污染全局命名空间吗? OP的版本没有这个问题。 – JBentley 2013-10-08 16:46:39

0

这是我的枚举用C如何工作++的理解。 (或者至少是我在Microsoft Visual C++中观察到的枚举行为。)

enum关键字不会像类那样创建范围。

然后为您的枚举'方向',全名是X ::方向。该枚举中的值仍然是类作用域的一部分,因此它们是X :: DIR_LEFT和X :: DIR_RIGHT。

当您在其他类中键入枚举枚举时,这不会更改枚举值的范围。

如果你想在多个位置分享它,我建议你将枚举放入一个名称空间的头文件中。

0

如果你想枚举值是既类的成员,该 解决方案是定义与枚举一个单独的类,并且 从它继承,如:

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成为模板,其派生类为 模板参数。

+3

它看起来像是继承的滥用:/ – 2011-03-15 18:09:09

+0

@Matthieu M.对于“误用”的定义是什么?这是C++中使用继承来共享 声明的更少或更少的标准技术,例如,请参阅std :: iterator。 – 2011-03-15 19:20:51

+0

这不是因为这个标准确实需要它。受保护的析构函数应该可以避免许多问题,但它仍然是“怪异的”,因为我现在可以通过多态非常不相关的类。 'typedef'在这里似乎是一个更好的选择。 – 2011-03-16 07:33:25

0

如果原始声明:

 
    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

这与重新定义enum完全相同。 – 2015-01-07 12:17:35

+1

正确,但是如果原始定义发生更改(例如左侧和右侧给出不同的值),则使用类Y的代码将继续正常工作。 – 2015-01-08 16:06:43