-1

I am trying to write some code which to the best of my knoledge is an example of a state machine.

What I have done so far is:

#include <map>
#include <iostream>

class StateInstance
{
    std::string m_string;

public: 

    StateInstance(const std::string& string)
        : m_string{string}
    {
    }
    
    std::string Get() const
    {
        return m_string;
    }
}instance_a("hello world"), instance_b("bring me coffee");

enum class StateInstanceOption
{
    STATE_INSTANCE_A,
    STATE_INSTANCE_B
}gCurrentState{StateInstanceOption::STATE_INSTANCE_A}; // global variable to hold current state "pointer" (really a flag)

class StateInstanceMapper
{
    std::map<StateInstanceOption, const StateInstance&> m_map;
    
public:
    
    StateInstanceMapper()
    {
        m_map.insert(std::pair<StateInstanceOption, const StateInstance&>(StateInstanceOption::STATE_INSTANCE_A, instance_a));
        m_map.insert(std::pair<StateInstanceOption, const StateInstance&>(StateInstanceOption::STATE_INSTANCE_B, instance_b));
    }
    
    const StateInstance& DoMap(/*const StateInstanceOption opt*/) const
    {
        return m_map.at(/*opt*/ gCurrentState);
    }
    
}mapper_instance;

int main()
{

    std::cout << mapper_instance.DoMap(/*gCurrentState*/).Get() << std::endl;

    gCurrentState = StateInstanceOption::STATE_INSTANCE_B;
    
    std::cout << mapper_instance.DoMap(/*gCurrentState*/).Get() << std::endl;
    
    return 0;
}

This works fine, however during the runtime of my program I only want there to exist a single state.

  • I want a way to prevent the user creating another instance of StateInstance, StateInstanceOption and StateInstanceMapper

For the example of a function, (in C), I would make the function static, and put the function in a seperate header, thus preventing it from being seen in other files.

Is there anything I can do to stop the end user creating more instances of these objects?

Since this question was disruptively closed so rappidly I cannot add an answer as an answer, however here is "the answer to this question"

#include <map>
#include <iostream>

class StateInstance
{
    std::string m_string;

public:

    // somewhat inconveniently, have to create an entirely new function for each possible instance of the state
    static StateInstance& get_instance_a()
    {
        static StateInstance instance_a("hello world");
        return instance_a;
    }
    static StateInstance& get_instance_b()
    {
        static StateInstance instance_b("bring me coffee");
        return instance_b;
    }

private:

    StateInstance(const std::string& string)
        : m_string{string}
    {
    }

    StateInstance(const StateInstance &) = delete;
    StateInstance& operator=(const StateInstance&) = delete;
    
public:

    std::string Get() const
    {
        return m_string;
    }
}; // instance_a("hello world"), instance_b("bring me coffee");

enum class StateInstanceOption
{
    STATE_INSTANCE_A,
    STATE_INSTANCE_B
}gCurrentState{StateInstanceOption::STATE_INSTANCE_A}; // global variable to hold current state "pointer" (really a flag)

class StateInstanceMapper
{
    std::map<StateInstanceOption, const StateInstance&> m_map;
    
public:

    static StateInstanceMapper& getInstance()
    {
        static StateInstanceMapper instance;
        return instance;
    }
    
private:
    
    StateInstanceMapper()
    {
        m_map.insert(std::pair<StateInstanceOption, const StateInstance&>(StateInstanceOption::STATE_INSTANCE_A, StateInstance::get_instance_a()));
        m_map.insert(std::pair<StateInstanceOption, const StateInstance&>(StateInstanceOption::STATE_INSTANCE_B, StateInstance::get_instance_b()));
    }
    
    StateInstanceMapper(const StateInstanceMapper &) = delete;
    StateInstanceMapper& operator=(const StateInstanceMapper &) = delete;
    
public:

    const StateInstance& DoMap(/*const StateInstanceOption opt*/) const
    {
        return m_map.at(/*opt*/ gCurrentState);
    }
    
}; //mapper_instance;

int main()
{

    //std::cout << mapper_instance.DoMap(/*gCurrentState*/).Get() << std::endl;
    std::cout << StateInstanceMapper::getInstance().DoMap().Get() << std::endl;

    gCurrentState = StateInstanceOption::STATE_INSTANCE_B;
    
    //std::cout << mapper_instance.DoMap(/*gCurrentState*/).Get() << std::endl;
    std::cout << StateInstanceMapper::getInstance().DoMap().Get() << std::endl;
    
    return 0;
}
Community
  • 1
  • 1
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225

1 Answers1

-1

What you are trying to create is a singleton, make the constructor private, and provide a function that will provide the singleton instance.

As an example of a singleton in C++:

class Singleton {
  std::string message;

  // Private constructor
  Singleton(const std::string& s) : message(s) {}

public:
  static Singleton& instance() {
    static Singleton s ("Hello!");
    return s;
  }

  const std::string& get_message() {
    return message;
  }
}
Nullrelation
  • 288
  • 5
  • 13