3

I want to initialize a static member variable inside the constructor of a particular instance. Is that a bad idea?

The situation is as follows. I have a static member variable that all instances of this class should share. Normally, I'd just use a static initializer. But, I don't have the necessary information needed to construct the static object until the constructor gets called. But of course, I don't want to create a new object every time the constructor gets called, so I want to do something like this.

class Foo
{
    static Bar * bar;
    Foo( Xyz xyz);
};

Bar * Foo::bar = nullptr;

Foo::Foo(Xyz xyz)
{
    if (Foo::bar == nullptr)
    {
         // initialize static bar 
         Foo::bar = new Bar(xyz);
    }
}

I know of course xyz migth be different for different calls to the constructor of Foo. That doesn't matter for me.

Is this bad software design? I feel a little weird initializing a static object inside the constructor. But it's not that different from the singleton design pattern. So maybe it is ok?

EDIT

Thanks for the comments guys. It seems like people are not a fan of this design. I will modify it so that I create a Bar once before the very first instantiation of Foo, and pass a Bar * as a parameter in Foo's constructor. Each Foo will have a pointer to a Bar, and I'll make sure all Foos are all pointing to the same Bar. Is that better?

user3240688
  • 1,188
  • 3
  • 13
  • 34

1 Answers1

1

Is this bad software design?

In general it would be considered so, yes. There are many reasons why the Singleton Pattern or having static variables in this way is considered bad design.


But it's not that different from the singleton design pattern. So maybe it is ok?

If you really want to make that a Singleton Pattern you should rather use Scott Meyer's technique:

class Foo
{
    static Bar* bar(Xyz xyz) {
        static Bar barInstance(xyz);
        return &barInstance;
    }
    Foo( Xyz xyz) : xyz_(xyz) {}

    void baz() {
        Bar* b = bar(xyz_);
        // use b ...
    }

private:
    Xyz xyz_;
};

This code will be thread safe, and avoids the need to check for a nullptr.


Though Bar should make up a Singleton on it's own then, and you use it in Foo whenever needed:

class Bar {
public:
    static Bar& getInstance(Xyz xyz) {
        static Bar barInstance(xyz);
        return &barInstance;
    }

private:
    Bar(Xyz xyz) : xyz_(Xyz) {}
    Bar(const Bar&) delete;
    Bar(Bar&&) delete;
    Bar& operator=(const Bar&) delete;
    Bar& operator=(Bar&) delete;

    Xyz xyz_;
};

class Foo {
public:
    Foo(Xyz xyz) barRef(Bar::getInstance(xyz)) {
                                      // ^^^ Notice 1st instance of Foo created
                                      //     wins to create the Bar actually
    }
private:
    Bar& barRef;
};
Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • *"But, I don't have the necessary information needed to construct the static object until the constructor gets called"*... – Jarod42 Jul 28 '16 at 17:12
  • 1
    @Jarod42 That's an indicator the design is flawed, and `Bar` shouldn't be in a static relation to `Foo`. I just try to clarify the difference from the _real_ Singleton Pattern. – πάντα ῥεῖ Jul 28 '16 at 17:20