Emiliano Emiliano - 3 months ago 13
C++ Question

shared_from_this called from constructor

I have to register an object in a container upon its creation.
Without smart pointers I'd use something like this:

a_class::a_class()
{
register_somewhere(this);
}


With smart pointers I should use
shared_from_this
but I can't use that in the constructor.

Is there a clean way to solve this problem? What would you do in a similar situation?
I'm thinking about introducing an
init
method to call just after creation and put everything in a factory function like this:

boost::shared_ptr<a_class> create_a()
{
boost::shared_ptr<a_class> ptr(new a_class);
ptr->init();
return ptr;
}


Is it fine or there is a standard procedure to follow in such cases?

EDIT: Actually my case is more complex. I have 2 object which shall maintain pointers each other. So the truth is I'm not "registering" but creating another object (let's say
b_class
) which requires
this
as a parameter.
b_class
receives
this
as a weak pointer and stores it.

I'm adding this because since you are giving me design advices (which are very appreciated) at least you can know what I'm doing:

a_class::a_class()
{
b = new b_class(this);
}


In my program
a_class
is an entity and
b_class
is one of the concrete classes representing the state (in the constructor it's just the starting state).
a_class
needs a pointer to the current state and
b_class
needs to manipulate the entity.

a_class
is responsible for creating and destroying b_class instances and thus maintains a shared_ptr to them but
b_class
need to manipulate
a_class
and thus maintains a weak pointer.
a_class
instance "survives"
b_class
instances.

Do you suggest to avoid using smart pointers in this case?

Answer

a_class is responsible for creating and destroying b_class instances

...

a_class instance "survives" b_class instances.

Given these two facts, there should be no danger that a b_class instance can attempt to access an a_class instance after the a_class instance has been destroyed as the a_class instance is responsible for destroying the b_class instances.

b_class can just hold a pointer to it's associated a_class instance. A raw pointer doesn't express any ownership which is appropriate for this case.

In this example it doesn't matter how the a_class is created, dynamically, part of a aggregated object, etc. Whatever creates a_class manages its lifetime just as a_class manages the lifetime of the b_class which it instantiates.

E.g.

class a_class;

class b_class
{
public:
    b_class( a_class* a_ ) : a( a_ ) {}
private:
    a_class* a;
};

class a_class
{
public:
    a_class() : b( new b_class(this) ) {}
private:
    boost::shared_ptr<b_class> b;
};

Note, in this toy example there is no need for a shared_ptr, an object member would work just as well (assuming that you don't copy your entity class).

class a_class
{
public:
    a_class() : b( this ) {}
private:
    b_class b;
};