Doddy
Doddy

Reputation: 1259

Constructing a static member variable late

I've got a static member of a class that needs to be constructed using the non-default constructor. The code is like this:

class MyClass
{
public:
   static void initialise(int arg1, int arg2)
   {
      static MyClass instance(arg1, arg2);
      _instance = instance;
   }

   static MyClass& instance()
   {
      return _instance;
   }

   /* Other non-static functions used with the return of instance()... */

private:
   MyClass(int arg1, int arg2)
      : _arg1(arg1), _arg2(arg2) {}

   static MyClass& _instance;
   int _arg1, _arg2;
};

I do this because I need one instance of the class for the lifetime of the application, however it needs to be constructed with arguments that are only known after configuration has been read. The superclass of MyClass will invoke an override in MyClass which depends on knowing these configuration items.

I've been trying to find a way to declare a static MyClass member which starts as just a placeholder so it can be constructed later, but my tests make it seem that this isn't possible. The test is below:

#include <cstdio>

class CNoDefCtor
{
public:
    CNoDefCtor(int arg1)
        : _arg1(arg1)
    {
        printf("%s\n", __func__);
    }

    virtual ~CNoDefCtor()
    {
        printf("%s\n", __func__);
    }

    static void Initialise(int arg1)
    {
        printf("%s\n", __func__);
        CNoDefCtor _instance(arg1); /* Actually construct here?!? */
    }

    static CNoDefCtor& instance()
    {
        return _instance;
    }

    int Arg1()
    {
        return _arg1;
    }

private:
    int _arg1;
    static CNoDefCtor _instance;
};

int main()
{
    printf("%s\n", __func__);

    CNoDefCtor ndc; /* Placeholder? */
    ndc.Initialise(1);
    printf("%d\n", ndc.Instance().Arg1());

    printf("%s\n", __func__);
}

So I guess my question is: how do you declare but not construct a static member? I thought that if it didn't have a default constructor it would be possible.

Please tell me I'm missing something simple and that there is an easy way to do this.

Upvotes: 0

Views: 58

Answers (1)

Sami
Sami

Reputation: 155

What you are trying to do here is a classical Singleton Class. https://en.wikipedia.org/wiki/Singleton_pattern

The class definition that you wrote in the first code block is fine and should work. The class static object will be initialized on the first call to initialise().

I think the problem is with your test code, you should not need the place holder variable in main. This would create an object of your singleton class, which you obviously you don't want.

So in short to correct your singleton class you have to obey following rules whenever writing a singleton class,

  1. Default Constructor in private.
  2. The initialization function is static.
  3. The static variable (instance) in your class definition should be a pointer or a reference variable.

So your new test class definition should look like,

class CNoDefCtor : public CAnnoyingClass
{
private:
    CNoDefCtor(int arg1)
        : _arg1(arg1)
    {
        printf("%s\n", __func__);
    }

public:
    virtual ~CNoDefCtor()
    {
        printf("%s\n", __func__);
    }

    static void Initialise(int arg1)
    {
        printf("%s\n", __func__);
        _instance = new CNoDefCtor(arg1);
    }

    static CNoDefCtor& instance()
    {
        return *_instance;
    }

    int Arg1()
    {
        return _arg1;
    }

private:
    int _arg1;
    static CNoDefCtor *_instance;
};

int main()
{
    printf("%s\n", __func__);

    CNoDefCtor::Initialise(1);
    printf("%d\n", CNoDefCtor::Instance().Arg1());

    printf("%s\n", __func__);
}

Upvotes: 1

Related Questions