Question

I was debugging an issue in some larger code and realized something strange about smart pointers and their polymorphic properties. This is best seen through the simple example:

#include <iostream>
#include <memory>

using namespace std;

class A {
public:
  virtual void who() {cout << "I am class A" << endl; };
}; 

class B : public A{
public:
  void who() {cout << "I am class B" << endl; };
}; 

int main(int argc, char *argv[])
{
  B b;  
  A * aptr = &b;
  aptr->who(); //Output: I am class B

  B * bptr = &b;
  bptr->who(); //Output: I am class B

  shared_ptr<A> sptr;
  sptr = make_shared<A>(b);
  sptr->who(); //Output: I am class A

  sptr = make_shared<B>(b);
  sptr->who(); //Output: I am class B

  return 0;
}

The first two outputs makes sense to me, but why can I access the member function defined in A (see the third output) when the only object I have initialized is of type B? In some sense, this is a nice trick for accessing members of the base class of an object of derived type. However, this still feels a bit spooky to me...

Can anyone explain why this behavior is possible with smart pointers but not regular pointers?

Was it helpful?

Solution

std::make_shared always creates a brand new object. That is,

sptr = make_shared<A>(b);

is more like

A* p1 = new A(b);

and not like

A* p2 = &b;

p1 and the return value of make_shared do not point at b at all.

OTHER TIPS

The following statement:

sptr = make_shared<A>(b);

is basically the same as:

sptr = shared_ptr(new A(b));

Instead of creating a shared_ptr from a pointer to B, you are creating a new A object with the copy constructor of A.

make_shared<A>(b) uses b to construct an object of type A, and points to that newly constructed object. This slices the B object, so the shared_ptr truly points to an A.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top