1
4

8 回答 8

3

Try using new C++11 feature - strongly typed enumerations. Thanks to it you will not have name collisions and you will end up with really strong type system.

于 2012-11-07T16:34:30.380 回答
3

You can use enum class for this

enum class State
{
    Accelerating,
    Breaking,
    Stopped
};

Then you'd refer to it as State::Breaking as you wanted. This of course requires c++11, see http://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations

于 2012-11-07T16:34:33.183 回答
2

An alternative I found was to, instead of namespace, use classes, but the problem is this way the project is not clear enough and classes can be instantiated. (Although I can cheat this problem with private constructors)

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

this works, but I'm not very clear if this is the best solution. I think there should be another way. I want opinions. What do you think?

于 2012-11-07T16:24:15.453 回答
2

In C++1x (the new version of C++ that was standardised last year), you can use strongly typed enumerations, which put the identifiers in the scope of the enum class itself (among other improvements). These are declared with enum class:

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

In the meantime, if you're stuck with a C++03 compiler or want to retain compatibility, just use class instead of namespace and declare the constructor private as you suggested in your own answer. You can make the entire class private if the outside world doesn't need to see it.

于 2012-11-07T16:34:34.437 回答
1

This sounds like a job for C++11's 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) ... }
于 2012-11-07T16:36:29.760 回答
1

If you use C++11, you can use

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;
}   
于 2012-11-07T16:37:13.337 回答
1

You can use a struct instead of a namespace if you are unable to use C++11 strongly typed enums:

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

This was something that we adopted for a while (until C++11 support) as it can be used everywhere unlike the namespace trick.

于 2012-11-07T16:42:21.567 回答
0

If you have so much in your class that you feel you need to sub-categorise it into namespaces, then your class has too many things.

You should move stuff out of it. In particular all these enums don't need to be members of a class. Why not keep them in the same namespace that the class is in?

于 2012-11-07T16:26:04.977 回答