Reputation: 15327
Suppose I need to call a free GlobalInitializer() before my constructor initializes any member variables. For example:
class Foo {
public:
Foo() : bar_()
{
// calling GlobalInitializer() here is too late
}
Bar bar_;
};
Calling GlobalInitializer() in Foo is too late because I need to call it before bar_ is initialized. My hacky work around for this has been to create a super-class:
class MyInitializer {
protected:
MyInitializer() {
GlobalInitializer();
}
};
class UglyFoo : public MyInitializer
{
public:
UglyFoo() : bar_()
{ }
Bar bar_;
};
UglyFoo gets the job done, but it requires this ugly MyInitializer class. Is there a cleaner design pattern or refactoring which will achieve the same result?
Additional Note: GlobalInitializer() is an expensive call that I want to avoid unless the user instantiates a Foo(). There are guards inside GlobalInitializer() against multiple calls. Also, there may be other classes, say FooBar, that also need to call GlobalInitializer(), but in one process, GlobalInitializer() will actually do work once (if Foo or FooBar is instantiated) or not even once (if there are no instantiations of Foo or FooBar).
Upvotes: 1
Views: 226
Reputation: 15327
Came across to me in a dream: change bar_ into a pointer:
class Foo {
public:
Foo()
{
GlobalInitializer();
// now we can call GlobalInitializer() in time
bar_ = new Bar;
}
~Foo()
{
delete bar_;
}
private:
Bar* bar_;
};
Upvotes: 0
Reputation: 258568
You should probably re-think your design.
A good design implies loose-coupling. If your object creation depends on a different method call to work, there's something seriously wrong there.
If you do need this, you should probably call GlobalInitializer
inside the constructor of bar_
, but the best way to go about this is re-thinking your design.
Upvotes: 1
Reputation: 82535
class Foo {
private:
struct Initializer {
Initializer() { GlobalInitializer(); }
};
Initializer initializer__; // declare before bar__ to ensure it is constructed first
public:
Foo() : bar_()
{
}
Bar bar_;
};
Upvotes: 4
Reputation: 28178
Presumably you could refactor whatever GlobalInitializer
initializes to not be global anymore. Then your options open up on how to give your class that data. You know, because globals are bad and all.
Upvotes: 0
Reputation: 39807
What you're doing seems to violate object oriented values as your classes are unreasonably dependent on something outside them; I would recommend redesigning your classes to avoid that instead.
That being said, an option that fits your design model without making each class inherit another is to create the MyInitializer class as a singleton object, and add a MyInitializer to each class that depends on this initialization. The singleton will only perform its initialization the first time it gets instantiated.
Upvotes: 0