0

I have a class named Colorblind which has getter and setter methods for a boolean variable called bool toggleColorBlind = false. I have multiple other classes such as Menu which a user can toggle the boolean variable and set it to true.

When I try to get the variable from another class, like Game, the boolean variable resets to its initial value when I instantiate the class and use the getToggleColorBlind() method within the class.

What can I do to prevent the boolean from resetting to its initial value and keep track of it when the class is instantiated and used? Could this be done a better way by using static or something?

Code example:

#include "Colorblind.h"

bool Colorblind::getToggleColorBlind()
{
    return mToggleColorBlind;
}

void Colorblind::setToggleColorBlind(bool state)
{
    mToggleColorBlind = state;
}
class Colorblind
{
public:
    Colorblind();

    bool toggleColorBlind(){return mToggleColor;}
    bool getToggleColorBlind();
    void setToggleColorBlind(bool state);

private:
    bool mToggleColorBlind = false;
};

Now the Menu is where a user can enable/disable colorblind mode which works as expected.

Colorblind colorblind;

while (std::getline(cin, command)) {
    if (command == "toggle colorblind") {
       bool isToggled = colorblind.getToggleColorBlind();
       if (isToggled == true) {
          colorblind.setToggleColorBlind(false);
       } else {
          colorblind.setToggleColorBlind(true);
       }
    {
}

Now my problem is when I try to access the mToggleColorBlind by doing Colorblind colorblind; colorblind.getToggleColorBlind() from any class such as Game to set colors etc.. The value is lost, how can I keep track of this.

JaMiT
  • 14,422
  • 4
  • 15
  • 31
stronghold051
  • 332
  • 2
  • 12
  • 1
    If you `Colorblind colorblind;` you are creating a separate copy of the flag (a new one for each Colorblind class). Maybe you want to make the flag variable in the Colorblind class static so there is only one for all instances of the Colorblind class? – Jerry Jeremiah May 31 '22 at 03:27
  • You might need a config or option instance which is injected into other instances like `Game` or make config instance globally accessible (not suggested, better not to use global singleton). Then every class may access to the same instance. – Louis Go May 31 '22 at 04:06
  • Why are you instantiating a new `Colorblind` object each time? Just reuse a single object instead. – Remy Lebeau May 31 '22 at 04:17
  • @RemyLebeau how would I reuse the object in a different class like `Game` I need to instanciate first to use methods no? – stronghold051 May 31 '22 at 04:19
  • @stronghold051 Yes, you need to instantiate it first. But nothing stops you from storing that instance somewhere that other classes can reach it. It would help if you would [edit] your question to show the actual code you are having trouble with, not just describe the code. It is hard to tell you how to fix the code when we can't see it. – Remy Lebeau May 31 '22 at 04:25

2 Answers2

1

If you goal is to share the same toggleColorBlind across all the instance of different classes like Menu and Game, then you can make toggleColorBlind a static data member as shown below. Making it a static data member would allow you use it without any instance of ColorBlind. This is because a static data member is not associated with any object of the corresponding class ColorBlind.

C++17

Here we use inline keyword for static data member.

class ColorBlind 
{
    public:
      inline static bool toggleColorBlind = false;
    //^^^^^^ ^^^^^^------------------------------------->note inline and static used here
};
class Menu 
{   public:
    //method that toggles 
    void invertColorBlind() const 
    {
        ColorBlind::toggleColorBlind = !ColorBlind::toggleColorBlind;
        std::cout<<"changed to: "<<ColorBlind::toggleColorBlind<<std::endl;
    }
};
class Game 
{
    public:
       void invertColorBlind() const 
       {
           ColorBlind::toggleColorBlind = !ColorBlind::toggleColorBlind;
           std::cout<<"changed to: "<<ColorBlind::toggleColorBlind<<std::endl;
       }
};
int main()
{
    std::cout<<"Initially toggleColorBlind is: "<<ColorBlind::toggleColorBlind<<std::endl;  //prints 0
    
    Menu m;
    //lets change toggleColorBlind using an instance of Menu
    m.invertColorBlind();                 //prints 1
    
    //toggle again 
    m.invertColorBlind();                //prints 0
    
    Game g; 
    
    //lets change toggleColorBlind using an instance of Game 
    g.invertColorBlind();               //print 1
    
}

The output of the program can be seen here:

Initially toggleColorBlind is: 0
changed to: 1
changed to: 0
changed to: 1

C++11

Prior to C++17, we could not use inline while defining a static data member inside class. So here we will provide an out-of-class definition for the static data member.

class ColorBlind 
{
    public:
      static bool toggleColorBlind;;
    //^^^^^^------------------------------------->note only the static used here
};

//define it outside class
bool ColorBlind::toggleColorBlind = false;

Working demo

Jason
  • 36,170
  • 5
  • 26
  • 60
  • This is what I am trying to do, however I get error "a nonstatic data member cannot be declared as inline" when I try to do `inline static bool toggleColorBlind = false;` – stronghold051 May 31 '22 at 04:56
  • @stronghold051 Note that `inline` here would work with C++17 and onwards. If you're using `C++14` or `C++11` then you've to skip the `inline` keyword and define the static data member outside class. See [demo with C++11 & C++14](https://onlinegdb.com/313rnK4Lu). I have added both versions in my answer as well. Check out my updated answer. Btw, which version of C++ are you using? – Jason May 31 '22 at 05:04
  • @stronghold051 Please note that when you're using static objects directly, you couple the code tightly. It might backfire in the long run ( maybe it's far away than your project life time), but still I'll suggest to study some design patterns to avoid that. I got backfired hardly multiple times. – Louis Go May 31 '22 at 05:39
0

You goal is : "Making multiple instances of classes accessing to a single instance of Option".

Most of time there are two ways:

  1. Dependency Injection: Make Option class accessible to all other instance
  2. Make Option class a global singleton.
    Better not to do it, because it makes your code hard to mock and test.

The draback of global singleton

  • Hard to decouple the code
  • You might need to resolve circular initialization issue when code gets more complex.

I will provide an example of #1, and if you really want global singletone, this might help.

Live Demo

#include <iostream>
#include "fmt/core.h"
class Option{
public:
    bool colorBlind() const {return mColorBlind;}
    void setColorBlind(bool enable){ mColorBlind = enable;}
private:
    bool mColorBlind = false;
};

class Game{
public:
    Game(Option& option): mOption(option){}

    void foo(){
        fmt::print("colorblind {}\n", mOption.colorBlind() );
    }
private:
    Option& mOption;
};

int main() {

    Option option;
    Game game{option};
    game.foo();
    option.setColorBlind(true);
    game.foo();
    return 0;
}

Louis Go
  • 2,213
  • 2
  • 16
  • 29