mardi 24 février 2015

Two phase construction to use shared_from_this() during object creation for derived classes

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