How to declare an static instance of a Class in C++?

21,409

Revisited and summarised

Option 1

You may simply declare and define a global instance of Game object. In a header file, e.g. game.h:

extern Game globalGameObj;

When you include game.h in a source file globalGameObj name becomes visible. You also need to create an actual object. In a source file, e.g. game.cc (outside of any class):

Game globalGameObj;

Access it by the variable name:

globalGameObj.do_some_work();

Option 2

Use a pattern often called singleton. Add the following to your Game class (game.h):

class Game
{
  public:
    static Game &shared_instance() {static Game game; return game;}

  private:
    // Make constructor private. Only shared_instance() method will create an instance.
    Game() {/*whatever initialisation you need*/}
};

You access Game instance with shared_instance() method:

Game::shared_instance().do_some_work();

You do not use anything like your static class PublicInstances in the above. C++ allows you to introduce a namespace (e.g. PublicInstances) to provide name isolation and keep your global objects in one place but it'll probably to be an overkill. In any case if you have few global objects then it is likely to be a bad design.

What option is better? Some people would argue that singleton pattern should be used. It guarantees that only a single instance is created. However both option 1 and option 2 have the same problem: they introduce a global object in your code with all disadvantages attributed to global variables. I'd say that singleton is a global object in disguise. I do not see deciding technical reasons in favour of either option so I'd say that it is a matter of personal taste.

Historical note :)

My first suggestion for Option 2 was to use a dynamically allocated Game object rather than a function local static object.

static Game *instance() {if (!_inst) _inst = new Game(); return _inst;}

Few people suggested that it was not the best way anymore, thank you Kal, argiopeweb and Simple. C++03 has issues initialising static objects in presence of threads. C++11 guarantees safe initialisation of statics.

C++11 draft, secion 6.7

such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. [...] If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

Share:
21,409
avatarbobo
Author by

avatarbobo

Updated on July 09, 2022

Comments

  • avatarbobo
    avatarbobo almost 2 years

    Some months ago I created a C# Project of a game called Vexed. Now I'm creating a Tetris, but in C++. Basically I want to use the same logic I used in the other project, it was a little bit like this:

    I created a Class called "Game" where there was all the information about the game. It had it's methods, variables and everything. Then, I created a static class called "PublicInstances" or something like that, and in that class I declared something like this:

    static class PublicInstances
    {
        public static Game vexedGame = new Game(); //This is C# and works.
    }
    

    It made it so simple to use then, because any change I made on the game was saved in that static instance of my class and I could access it anywhere on the project. I want to know how to do exactly that with C++, to create a public or global instance of my class Game so I can access it and change it everywhere and have everything updated in any Form or class of my project. I would really appreciate your help.

    // Sorry if my English isn't the best ^^

    • Kal
      Kal over 10 years
      if u really want a global, u don't have to put it inside a class. just declare it in a header and define in a source file. but globals (or globally accessible statics) are usually bad design
    • avatarbobo
      avatarbobo over 10 years
      My main problem is that I usually travel between Forms, and I need to get information from one place to another, how could I change the use of a global variable or class?
    • Ben Voigt
      Ben Voigt over 10 years
      It sounds as if TetrisGame should be a namespace, not an object. That will also eliminate the need to define a class type for it.
    • MasterMastic
      MasterMastic over 10 years
      I agree with the fact that this design is probably a bit flawed but, that's beyond the question. Anyways, I'd still suggest you to reconsider.
  • Adam
    Adam over 10 years
    You've declared S::_inst but you haven't defined it.
  • Kal
    Kal over 10 years
    also a better way to do this is static S& instance() { static S inst; return inst; }
  • dmitri
    dmitri over 10 years
    @BenVoigt Is it not clear what you mean, no class needed. Game class is there by default.
  • Kal
    Kal over 10 years
    @dmitri actually u can; the ctor is called when the function is called for the first time. also u can pass parameters to the ctor, just like static S inst { 1, 2 }; or whatever
  • Elliot Robinson
    Elliot Robinson over 10 years
    In regards to the drawback with option #2, this is no longer the case with C++11 as per n2660: open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm
  • Matthew Pigram
    Matthew Pigram over 10 years
    @avatarbobo the way it works is by essentially returning a static reference to a single instance of itself, instansiation is made impossible outside of the class by making the default constructor private