Search code examples
c++inheritanceshared-ptr

How does a shared_ptr handle copy to a pure virtual base class?


Class B expects to receive an instance of shared_ptr<IError>.
Class A implements IError and is passed by value to the constructor of B.

I would like to understand how this scenario is handled. How does the shared_ptr as a template class handle the conversion to IError?

In a simple case where B receives shared_ptr<A> I assume the copy constructor is called and the reference counter is increased. However since IError is pure virtual a normal copy constructor invocation seems not to be case here?

// Example program

#include <iostream>
#include <string>

class IError 
{    
    public:
        virtual ~IError(){};
        virtual void OnError() = 0;
};

 

class A : public IError 
{
    public:
       A(){};
       void OnError(){std::cout << "Error Occured" << std::endl;} 
};

class B
{
  public:
     B(std::shared_ptr<IError> errorReporter): mErrorReporter(errorReporter){}
     void Action(){mErrorReporter->OnError();}

  private:   
     std::shared_ptr<IError> mErrorReporter;
};

int main()
{
    auto objA = std::make_shared<A>();
    auto objB = std::make_shared<B>(objA);
    objB->Action();
}

Solution

  • Debugging time! Let's find out what happens by using the tools we have available as developers.

    The memory of the shared_ptr objA looks like this (type &objA in the memory window; it will be replaced by its address):

    objA

    It has a pointer to the object (000002172badd8e0) and a pointer to the control block.

    The control block looks like this (copy and paste the second value into a new memory window):

    objA control block

    It has a pointer to the allocator (first 2 columns), the reference count (1) and the weak reference count (0 + offset 1).

    After objB has been created, the control block of objA has changed to a reference count of 2:

    objA control block after copy

    And the shared_ptr objB looks like this:

    objB

    It points to the a shared pointer and to the control block.

    Shared pointer of objB

    The shared pointer in objB points to the same object as before (000002172badd8e0), so no copy of the actual object has been made.

    The control block of objB indicates that objB only has a reference count of 1:

    objB control block

    a normal copy constructor invocation seems not to be case here?

    Correct. No copy of the object is made, as we can confirm with a debugger. But a copy of the shared_ptr has been made.