I have a setup with a base class that inherits from enable_shared_from_this
class Object : public enable_shared_from_this<Object>
{ ... };
I inherit from enable_shared_from_this because I need to call shared_from_this() every so often. In certain derivations of Object, I need to call shared_from_this() from with in the constructor, which can't be done:
class Thing : public Object
{
public:
Thing() : Object(...)
{ doSomething(shared_from_this()); /* error */ }
};
So a work around is two-phase construction.
class Thing : public Object
{
public:
Thing() : Object(...) { }
void Init() { /* safe to call shared_from_this here */ }
};
A valid way to create a Thing object would be:
shared_ptr<Thing> thing = make_shared<Thing>();
thing->Init();
This is not very nice and error prone but at least it works. However, now there's an issue with further inheritance:
class Bling : public Thing
{
public:
Bling() : Thing(...) { ... }
void Init() { /* safe to call shared_from_this here */ }
};
// How do we create a Bling object?
shared_ptr<Bling> bling = make_shared<Bling>();
static_cast<Thing*>(bling.get())->Init(); // horrible
bling->Init();
// Maybe Bling::Init should look like:
// Bling::Init() { Thing::Init(); /* + other stuff */ }
// then we could do:
shared_ptr<Bling> bling = make_shared<Bling>();
bling->Init(); // etc
Is there a safer or cleaner way to do this? For example, API wise its less error prone to make the constructors for Object, Thing and Bling private and use a static Init() function that creates the shared_ptr:
static shared_ptr<Bling> Bling::Init() {
auto bling = make_shared<Bling>();
Bling::init(bling);
return bling;
}
static void Bling::init(shared_ptr<Bling> bling) {
/* chain parent class init */
Thing::init(bling); // sig: Thing::init(shared_ptr<Thing>);
/* do init stuff */
}
// calls Object(), Thing(), Bling(),
// Object::init(), Thing::init(), Bling::init()
auto bling = Bling::Init();
Basically I'm looking for patterns to implement object creation in a way where I can use a shared_ptr to the object during creation. I need to allow for basic inheritance. I would like suggested methods to consider end-user ease of use and developer maintainability.
Aucun commentaire:
Enregistrer un commentaire