OK, I started using shared-pointers and pass shared-pointers as much as possible. No conversion to raw pointers anymore. This works good, except in this specific case:
Suppose we have a class that also is an observer on another class, like this:
class MyClass : public IObserver
{
public:
MyClass (std::shared_ptr<SomeOtherClass> otherClass);
void DoSomethingImportant();
private:
std::shared_ptr<SomeOtherClass> m_otherClass;
};
This class is used like this in my application:
std::shared_ptr<MyClass> myInstance(new MyClass(otherInstance));
...
myInstance->DoSomethingImportant();
MyClass gets a shared-pointer to another class and stores this in its m_otherClass data member. In the DoSomethingImportant method, the MyClass instance does lots of important things, including registering itself as an observer on m_otherClass, like this:
m_otherClass->registerObserver(this);
The problem is that the registerObserver method is defined like this:
void registerObserver (std::shared_ptr observer);
It expects a shared pointer, but 'this' is a raw pointer, not a shared one.
I see three ways of solving this:
This problem makes it obvious that shared-pointers are just an add-on to C++ (I don't think you have the same problem in other languages/environments like C# (or .Net in general) and Java).
Any other suggestions or tricks on how to handle this situation?
What you need is probably the enable_shared_from_this
and shared_from_this
facilities. The docs are here
Note that you cannot use shared_from_this
until the constructor has fully completed and the object is already owned by another shared_ptr
.
struct test : boost::enabled_shared_from_this<test>
{
test() {
// shared_from_this(this); // error, still not owned by another shared_ptr
}
boost::shared_ptr<test> shared() {
return shared_from_this(this);
}
};
int main() {
test * t = new test;
// boost::shared_ptr<test> p = t->shared(); // error, not yet owned by other shared_ptr
boost::shared_ptr<test> owner( t );
boost::shared_ptr<test> p = t->shared(); // [*] ok, "owner" owns the object
}
[*] This part of the example is silly, you could just copy owner into p, instead of calling the method. It is just presented to note when it is ok or not to called shared_from_this
inside the test
methods.