Reputation: 1
class Base
{
bool a;
};
class Derived : public Base
{
bool b;
};
void main()
{
std::shared_ptr<Base> base(new Derived());
}
So in this example the raw pointer of shared_ptr will point to an instance of Base, NOT Derived. Which I do not understand.
class Base
{
virtual void foo() {}
bool a;
};
class Derived : public Base
{
virtual void foo() {}
bool b;
};
void main()
{
std::shared_ptr<Base> base(new Derived());
}
But in this case the raw pointer of shared_ptr does point to Derived? I'm sure I'm missing something. can someone explain to me why this is happening?
Upvotes: 0
Views: 314
Reputation: 153929
First, the use of std::shared_ptr
here is a red herring. In
this case, both std::shared_ptr
and a raw pointer behave
exactly the same. In both cases, the expression new Derived()
returns a Derived*
which points to the entire object. And in
both cases, using it to initialize a pointer to Base
, be it
a raw pointer or any reasonably designed smart pointer will
cause the Derived*
to be converted to a Base*
, which points
to the Base
sub-object in the Derived
. The Derived
object
still exists, however, and can be accessed in several different
ways: via virtual functions, by using std::dynamic_cast
if
Base
is polymorphic (has at least one virtual function), by
using std::static_cast
if you're 100% sure that the pointed to
object actually is a Derived
, and probably some others I've
not thought of. In your first case, only the last is possible,
since in the first, Base
is not polymorphic. In both of your
examples, however, the pointer points to a Base
, which is
a subobject of a larger Derived
.
There are some differences between std::shared_ptr
and a raw
pointer. For example, in your first example, replacing
std::shared_ptr<Base>
with Base*
and manually deleting
through the pointer will result in undefined behavior;
std::shared_ptr
has extra complications to avoid this. (But
the complications aren't without their drawbacks. Give Base
a virtual destructor, as it should have, and then make the
destructor of Derived
private, for whatever strange reason,
and your first example won't compile.)
Upvotes: 1
Reputation: 3222
In the first example, the classes do not have a virtual table, since there are no virtual functions. This means, that since the shared_ptr expects a static type of Base, it will store a Base. The second case also stores a Base, but the existence of a virtual table allows you to see that the dynamic type of the object is Derived.
Upvotes: 2