To help better understand my question, I'm referring to a topic discussed in the book "The C++ Programming Language 4th edition" chapter 27 section 2.1.
The author is talking about the danger of polymorphic types and built-in arrays. He gives the following example:
void maul(Shape∗ p, int n) // Danger!
{
for (int i=0; i!=n; ++i)
p[i].draw(); //looks innocent; it is not
}
void user()
{
Circle image[10]; // an image is composed of 10 Circles
// ...
maul(image,10); // ‘‘maul’’ 10 Circles
// ...
}
We're told that Shape is an abstract size of size 4 and Circle inherit Shape and add an extra 2 members, center and radius which adds to the type size, hence, sizeof(Circle)>sizeof(Shape)
.
Now the author explains that given the following view for example:
user() view: image[0] image[1] image[2] image[3]<br/>
maul() view: p[0] p[1] p[2] p[3]
The call of p[1].draw()
(emphasis on p[1], for p[0] it will call the right function) will fail because there's no virtual function pointer where it's expected.
Now I know how virtual function tables works, but I don't understand how the size of the type or its layout affect a virtual function call? When the compiler see a call to a virtual function doesn't it replace it with something similar to:
p[1]._vfptr->draw_impl();
Assuming I'm right, how is the size of the derived object/its layout broke the call for it.
Circle
objects? – Brian Biimage + 1 != p + 1
? – Jarod42p[1]
is not even a correctShape
. – Jarod42