什么是类中名称空间的好替代方法

What is a good alternative to namespaces within classes?

本文关键字:方法 空间 什么      更新时间:2023-10-16

问题是C 不允许在类中命名空间声明(我在Internet上搜索并找到了;如果不是真的,请说出来)问题?

上下文:我的班级内有一个枚举。

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::StoppedGameCharacter::DrivingState::Stopped)那我该怎么办?

尝试使用新的C 11功能 - 强烈键入枚举。多亏了它,您将没有名字碰撞,最终将获得真正强大的类型系统。

您可以将枚举类用于此

enum class State
{
    Accelerating,
    Breaking,
    Stopped
};

然后,您将其称为状态::打破。当然,这需要C 11,请参见http://en.wikipedia.org/wiki/c+++11#stronglonglonglong_typed_enumerations

在C 1X中(去年标准化的C 的新版本),您可以使用强烈键入的枚举,将标识符放在枚举类本身的范围(其他改进)。这些用enum class声明:

class GameCharacter {
public:
    enum class State {
        Running,
        Walking,
        Stopped    // Referred to as GameCharacter::MovingState::Stopped.
    };
    ...
};

与此同时,如果您遇到了C 03编译器或想要保留兼容性,只需使用class而不是namespace,然后按照您自己的答案中建议的按照您的建议来声明构造函数。如果外界不需要看到整个class

我发现的另一种替代方案是使用类,而是使用类,但是问题是该项目不够清晰,可以实例化类。(尽管我可以用私人构造函数欺骗这个问题)

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.
        };
    };
    ...
};

这有效,但是我不清楚这是最好的解决方案。我认为应该有另一种方式。我想要意见。你怎么看?

这听起来像是C 11的强烈打字的工作。

class GameCharacter {
public:
    enum class MovingState {
        Running,
        Walking,
        Stopped
    };
    ...
    void f(Movingstate m) { if (m == MovingState;:Running) ... }
};
void f() { if (mm == GameCharacter::MovingState::Running) ... }

如果使用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;
}   

如果您无法使用C 11强键入枚举,则可以使用struct而不是名称空间:

class GameCharacter {
public:
    struct MovingState {
        enum Enum {
            Running,
            Walking,
            Stopped
        };
    }
    ...
};

这是我们一段时间采用的东西(直到C 11支持),因为它可以与名称空间技巧不同。

如果您的班级有很多东西,以至于您需要将其子类别化为名称空间,则您的类有太多东西

您应该将东西从中移出。特别是所有这些枚举都不需要成为班级的成员。为什么不将它们保留在同一级别的命名空间中?