0

I'm trying to create simple game in C++. At one point I want to have some setting, save and load from config file.
The config file should be read from the beginning, and should be accessible anywhere it needed.

  • So far I only see Singleton pattern as a solution.
  • Another way is to create an object an pass it down, but it can mess up the current code.
  • I've also search and found something called Dependency Injection.
  1. Is dependency injection useful in C++
  2. Which design patterns can be applied to the configuration settings problem?

But I don't quite understand it, you still have to create an object in main and pass it down, right? Singleton is quite simple, but some consider it antipattern, while pass it down the tree can mess up my current code. Is there any other Patterns?

P/S: I'm also curious how games load their setting.

Phineas
  • 159
  • 2
  • 10
  • Configuration is often a [cross-cutting concern](https://en.wikipedia.org/wiki/Cross-cutting_concern) and kind-of makes a mess of OOP. Assuming the config structure does not contain any modifiable state, the program itself does not change the configuration, most of my arguments against a singleton go away. But watch out for the [Static Initialization order Fiasco](https://stackoverflow.com/questions/3035422/static-initialization-order-fiasco). – user4581301 Aug 25 '20 at 17:31
  • If you use a [Meyers Singleton](https://stackoverflow.com/a/1008289/4581301) to avoid SIOF, take care that you do not use the configuration during post-`main` shutdown because with a lazy-load it can be tricky to get the destruction ordering right. Not this is only a problem if you have other global variables floating around. My experience is one once global, the singleton, sneaks in, others follow. Exercise restraint and this should be a non-issue. – user4581301 Aug 25 '20 at 17:32

1 Answers1

0

I would suggest something simple as the following example, which circumvents any singleton-related or initialization order issue:

struct global_state
{
    config _config;  
};

struct game_state
{
    global_state& _global_state;
};

int main()
{
    global_state globals{load_config_from_file()};
    game_state game{globals};
    game.run();
}

Since _global_state is a member of game_state, it can be used in member functions without the need of explicitly passing it as a parameter:

void game_state::update_ui()
{
    const float text_size = _global_state._config.get_float("text_size");
    _some_text.set_size(text_size);
}
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416