Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling multiple states in a C++ class

Tags:

c++

What would be the most efficient and modern way of handling states in C++ class? At the moment I am using multiple bools, but the more I states I add the harder is to maintain. For example if I have a class called VideoPlayer and it has four bools defining different states. If we add set methods for each bool we need to unset all the other bools.

class VideoPlayer
{

public:
    void play()
    {
        play_ = true;
        pause_ = false;
        stop_ = false;
        reset_ = false;
    }

    void stop()
    {
        stop_ = true;
        play_ = false;
        pause_ = false;
        reset_ = false;
    }

private:
    bool play_;
    bool pause_;
    bool stop_;
    bool reset_;
};
like image 353
sabotage3d Avatar asked Feb 05 '23 15:02

sabotage3d


1 Answers

Your design suffers from it being easy to be in a bad state (e.g. what if both stop_ and play_ are both true?

You should use an enum to define a set of finite-states of which only 1 can be active at any given point in time.

C++'s enum types are somewhat different from Swift, Java and C#'s enum: they're unscoped and are more permissive with implicit conversions - behaving somewhat similarly to #define.

C++11 adds enum class which is very similar to C#'s enum. There is no built-in functionality similar to the flexibility of Java or Swift's enums, however.

You will want something like this:

enum class PlayerState {
    Stopped,
    Playing,
    Paused
}

If Reset is not a state, but a verb, then it should not be in the enum definition.

class VideoPlayer {
private:
    PlayerState state;
public:
    VideoPlayer() :
        state( PlayerState::Stopped )
    {

    }

    void play() {

        switch( this->state ) {
            case PlayerState::Stopped:
                 // start video here, only change `state` when complete.
                // you might want to add a "BeginPlaying" (e.g. `LoadingFileFromDisk`) state value too.
                this->state = PlayerState.Playing;
                break;
            case PlayerState::Playing:
                throw VideoPlayerStateExeception("Already playing");
            case PlayerState::Paused:
                this->resume();
                break;
        }
    }


}
like image 163
Dai Avatar answered Feb 08 '23 17:02

Dai