问题是C ++不允许在类中使用命名空间声明。(我在网上搜索并发现了这个;如果不是这样,请说出来)那么,什么是欺骗这个问题的最佳方法?
上下文:我的类中有一个枚举。
class GameCharacter {
public:
enum MovingState {
Running,
Walking,
Stopped
};
...
};
OBS:这个例子不是真的,完全是假设的。
C ++定义了枚举名称在类范围内,然后使用这些状态我必须直接从类名(GameCharacter::Running
,或using GameCharacter::Running
)使用范围运算符。
我认为这很糟糕,因为属于枚举的名称在类范围内;我想要一个RunningState枚举的范围。 (以这种方式访问它:GameCharacter::MovingState::Running
)
我的第一个想法是创建一个命名空间,用于定义枚举的范围。
class GameCharacter {
public:
// does not compile
namespace MovingState {
enum State {
Running,
Walking,
Stopped
};
};
...
};
但是C ++禁止它。此代码无法编译。 (main.cpp:3:5: error: expected unqualified-id before ‘namespace’
)
我之所以尝试这样做是因为有可能创建一个名称在同一范围内的第二个枚举。这可能会导致名称冲突。
class GameCharacter {
public:
enum MovingState {
Running,
Walking,
Stopped
};
enum DrivingState {
Accelerating,
Breaking,
Stopped // Compilation error: conflicts with previous declaration ‘GameCharacter::MovingState GameCharacter::Stopped’
};
...
};
(我的想法是,在这种情况下,状态应该被称为GameCharacter::MovingState::Stopped
和GameCharacter::DrivingState::Stopped
)
然后,我该怎么办?
答案 0 :(得分:3)
尝试使用新的C ++ 11功能 - strongly typed enumerations。多亏了它,你就不会有名字冲突,你最终会得到一个非常强大的类型系统。
答案 1 :(得分:3)
您可以为此
使用枚举类enum class State
{
Accelerating,
Breaking,
Stopped
};
然后你可以将它称为State :: Breaking,如你所愿。 这当然需要c ++ 11,请参阅http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations
答案 2 :(得分:2)
我发现的一个替代方法是使用类而不是命名空间,但问题是这样的方式项目不够清晰,类可以实例化。 (虽然我可以用私人构造函数来欺骗这个问题)
class GameCharacter {
public:
class MovingState {
MovingState();
/* or, in C++11:
* MovingState() = delete;
*/
public:
enum State {
Running,
Walking,
Stopped // Referred as GameCharacter::MovingState::Stopped.
};
};
class DrivingState {
DrivingState();
/* or, in C++11:
* DrivingState() = delete;
*/
public:
enum State {
Accelerating,
Breaking,
Stopped // Referred as GameCharacter::DrivingState::Stopped.
};
};
...
};
这有效,但我不太清楚这是否是最佳解决方案。我认为应该有另一种方式。我想要意见。你觉得怎么样?
答案 3 :(得分:2)
在C ++ 1x(去年标准化的新版C ++)中,您可以使用strongly typed enumerations,它将标识符放在枚举类本身的范围内(以及其他改进)。这些是用enum class
:
class GameCharacter {
public:
enum class State {
Running,
Walking,
Stopped // Referred to as GameCharacter::MovingState::Stopped.
};
...
};
与此同时,如果您坚持使用C ++ 03编译器或想要保持兼容性,只需使用class
而不是namespace
,并按照您的建议声明构造函数为private你自己的答案。如果外界不需要查看,您可以将整个class
设为私有。
答案 4 :(得分:1)
这听起来像C ++ 11的作业Strongly Typed Enumerations。
class GameCharacter {
public:
enum class MovingState {
Running,
Walking,
Stopped
};
...
void f(Movingstate m) { if (m == MovingState;:Running) ... }
};
void f() { if (mm == GameCharacter::MovingState::Running) ... }
答案 5 :(得分:1)
如果您使用C ++ 11,则可以使用
class GameCharacter {
public:
enum class DrivingState { Accelerating, Breaking, Stopped };
enum class WalkingState { Stopped, Running, Walking };
DrivingState driving_state() { return ds_; }
void set_driving_state(DrivingState ds) { ds_ = ds; }
WalkingState walking_state() { return ws_; }
void set_walking_state(WalkingState ws) { ws_ = ws; }
DrivingState ds_;
WalkingState ws_;
};
int main() {
GameCharacter g;
g.set_walking_state(GameCharacter::WalkingState::Stopped);
g.set_driving_state(GameCharacter::DrivingState::Stopped);
return 0;
}
答案 6 :(得分:1)
如果您无法使用C ++ 11 strongly typed enums,则可以使用结构而不是命名空间:
class GameCharacter {
public:
struct MovingState {
enum Enum {
Running,
Walking,
Stopped
};
}
...
};
这是我们已经采用了一段时间(直到C ++ 11支持),因为它可以在任何地方使用,不像命名空间技巧。
答案 7 :(得分:0)
如果你的课程中有这么多,你觉得你需要将它细分为命名空间,那么你的课有太多的东西。
你应该把东西搬出去。特别是所有这些枚举不需要是类的成员。为什么不将它们保存在类所在的命名空间中?