How to make clone method using shared_ptr and inherit from enable_shared_from_this

I saw that a useful way to write a clone method that returns boost :: shared_ptr is to do

class A { public: shared_ptr<A> Clone() const { return(shared_ptr<A>(CloneImpl())); } protected: virtual A* CloneImpl() const { return(new A(*this)); } }; class B : public A { public: shared_ptr<B> Clone() const { return(shared_ptr<B>(CloneImpl())); } protected: virtual B* CloneImpl() const { return(new B(*this)); } }; 

This allows the use of covariance with a regular pointer, while still wrapping it in the security of a smart pointer. My problem is that my class B should inherit from boost :: enable_shared_from_this, because right after building it needs to register itself with a separate class, passing a generic pointer to itself. I have a Create method that completes the creation and registration to make sure they always meet together. However, the implementation of the clone method described above cannot cope with this requirement. Registration cannot happen in CloneImpl, since shared_ptr does not yet exist, "owning" the object, preventing the call to shared_from_this (), and if this logic is not in a virtual function, then shared_ptr pointing to B does not know about the requirements for registering B when cloning . What is the best way to deal with this problem?

+7
c ++ shared-ptr
source share
1 answer

Since you already implement covariance of the public interface yourself through non-virtual Clone() functions, you can refuse covariance for the CloneImpl() functions.

If you only need shared_ptr and never a raw pointer, so you can do the following:

 class X { public: shared_ptr<X> Clone() const { return CloneImpl(); } private: virtual shared_ptr<X> CloneImpl() const { return(shared_ptr<X>(new X(*this))); } }; class Y : public X { public: shared_ptr<Y> Clone() const { return(static_pointer_cast<Y, X>(CloneImpl())); // no need for dynamic_pointer_cast } private: virtual shared_ptr<X> CloneImpl() const { return shared_ptr<Y>(new Y(*this)); } }; 

CloneImpl() will always return shared_ptr<Base> , and now you can register your object inside the B::CloneImpl() function and return registerd shared_ptr.

+7
source share

All Articles