Home > front end >  C static class member with private constructor
C static class member with private constructor

Time:10-13

Why can a private constructor be used in this case? I can't explain it to myself. In this case, I initialize the class field (the type of which is the same class) from the outside, since it is static.

Edit1: I use C 17 (gcc 11.2).

#include <iostream>

using namespace std;

class MainMenu {
public:
    MainMenu(const MainMenu& other) = delete;
    MainMenu& operator=(const MainMenu& other) = delete;
    static MainMenu& GetInstance() { return _instance; }

private:
    static MainMenu _instance;

    MainMenu() { cout << __PRETTY_FUNCTION__ << endl;}
};

// HERE HERE HERE!!
MainMenu MainMenu::_instance = MainMenu(); // Or just MainMenu MainMenu::_instance;

int main() {
    MainMenu::GetInstance();
    return 0;
}

Result:

MainMenu::MainMenu()

Process finished with exit code 0

CodePudding user response:

I would use the following mental model for it:

a. Note that your are instantiating the variable (it would have an incomplete type at the class's scope, so it cannot be inline withing the class's scope), not actually (re)assigning it

b. it is already declared global/static on class's scope so technically the constructor is called within the class. That's fine, even with the constructor being private, because it's called from exactly that privately accessible scope. True, the definition outside looks off, but that does not matter, as the declaration specifies its scope.

Excerpt from C 17 standard:

12.2.3.2 Static data members [class.static.data]

2 The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void. The definition for a static data member that is not defined inline in the class definition shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator. The initializer expression in the definition of a static data member is in the scope of its class (6.3.7)

And the example is your case exactly:

class process {
  static process* run_chain;
  static process* running;
};

process* process::running = get_main();
process* process::run_chain = running;

Any additional citations from the C standard to explain it in a better way are most welcome. :)

  •  Tags:  
  • c
  • Related