I'm creating a GUI in my C++ application and I have a class called GUIObject
which is base class for all other components, like for example Button
, CheckBox
, Window
etc.
I also have a class GUIObjectsStorage
, which consists of all GUIObject
s that are created. So far I've been working with raw pointers, so I just had this constructor for GUIObject
class:
GUIObject::GUIObject() :
{
GUIObjectsStorage::Instance().addObject(this);
}
And it was ok for my needs, because whenever I wanted to access specific object, I just took it from GUIObjectsStorage
. But now I'm trying to move into use of smart pointers, so that GUIObjectsStorage
now stores array of std::shared_ptr<GUIObject>
instead of raw pointers and I can't use my constructor as I used it before:
GUIObject::GUIObject() :
{
GUIObjectsStorage::Instance().addObject(std::shared_ptr<GUIObject>(this));
}
because for example:
// Somewhere in code
std::shared_ptr<Button> bt = std::shared_ptr<Button>(new Button());
Basically I'd now have two shared_ptr
s (one here, second in GUIObjectsStorage
, because it was added in Button
's constructor) which both have reference count = 1, yet both point to the same object in memory. Then if one of them dies, object itself is being destroyed too.
So I came up with an idea to maybe make private constructor for all classes inheriting from GUIObject
and create a static method which would create and return std::shared_ptr
and it's copy add to GUIObjectsStorage
. This way I could have shared_ptr
s with reference count = 2 which is correct:
class Button : public GUIObject
{
private:
// ...
Button();
public:
// ...
static std::shared_ptr<Button> create();
}
std::shared_ptr<Button> Button::create()
{
std::shared_ptr<Button> bt = std::shared_ptr<Button>(new Button());
GUIObjectsStorage::Instance().addObject(bt);
return bt;
}
By hiding constructor I could be sure that nobody will create an object in different way than by using create()
method.
But is this good way of designing this? If not, what could be a better solution for this problem?
The is a classic use of a Factory for making objects.
That said, you might not need this. Do you know when widgets are no longer needed? GUI managers like this often do. If so, the commenter is right: designate an owner of the object, let it delete it, and you're set.
You could consider inheriting from enable_shared_from_this.
Then after you have a shared_ptr to the object, you can use shared_from_this() to get the shared_ptr that holds the object.