Reputation: 157
The C++ standard says "... the interpretation of the call of a virtual function depends on the type of the object for which it is called (the dynamic type)" (p. 252) and then
"if a pointer p
whose static type is 'pointer to B
' is pointing to an object of class D
, derived from B
, the dynamic type of *p
is D
" (p. 2). Here B
is a base class and D
a derived class.
This seems to suggest (to me) that if I say
D d;
B *p = new B();
*p = d;
then, if f()
is virtual in B
, p->f()
should call D::f()
, which is wrong. I guess I'm not clear about the meaning of "pointing to an object of class ...". I know, if I say p = &d
, then D::f()
is called, but I would like to know why the above is wrong.
Upvotes: 2
Views: 117
Reputation: 371
As TartanLlama said above, in the third line you're "wrongfully" assigning d to the object pointed by P, thereby what we refer to as Slicing occurs. From Professional C++,
...When upcasting, use a pointer or reference to the superclass to avoid slicing
D d;
B *p = new B();
*p = d;
This means the correct code evaluates to the code hereunder
D d;
B *p = new B();
p = &d;
OR
D d;
B *p = new B();
p = static_cast<B*>(&d);
Consequently, the dynamic type of the object pointed by p (*p) is still D. This allows you to switch back and forth through the inheritance hierarchy by upcasting or downcasting the pointer to the child class and not the object.
Upvotes: 1
Reputation: 171167
The crux of the answer is that in C++, the dynamic type of an object can never change. You're thinking about the assignment expression *p = d
as somehow completely replacing the object at *p
with the object d
. But that's not what happens. In C++, an object can never truly replace another.
Since class types are involved, *p = d
just calls the assignment operator of class B
(that's the static type of *p
) with an argument D
. An object in C++ can only be acted upon, it cannot really be "replaced."
Sure, we talk about copying objects, assigning to them etc. But that's just for convenience, as most of the time, the very exact semantics doesn't matter and thinking about =
as assigning one object to another is simple. But deep down, it's either a function call on the target object (for class types), or copying the value of some bits into the target object's space (for primitive types). The target object itself always remains.
Upvotes: 2
Reputation: 65630
D d;
B *p = new B();
*p = d;
That final line assigns d
to *p
. This means it will copy the D
instance using the B
assignment operator and the object will be sliced. The dynamic type of *p
in that case is still B
.
p = &d;
That assigns the pointer to the D
object to p
. No slicing will occur in this case, because you are just assigning the pointers, not the objects themselves. The dynamic type of *p
in this case is D
.
Upvotes: 4