Initializers – whoops!

I mentioned initializers yesterday, here’s what I’m talking about:

std::vector<Shape> shapes = {
	Cube(glm::vec3(1.5, 0, 0)),
	Cube(glm::vec3(-1.5, 0, 0))
};

This stores objects instead of references, and then the for loop looks like this:

for (auto &shape : shapes)
{
	// do stuff with shape
}

You can take out the &, too, and I’m going to be brutally honest with y’all I don’t know what the difference is.

Don’t matter though, because guess what – this doesn’t work! All of the Cubes act like Shapes, even though I’ve dutifully marked the functions as virtual. Why is this? Turns out there is something called “Object slicing”. When I assign a Cube to a Shape, The piece of Cube that makes it different from Shape gets sawed off, and there’s just a Shape left that doesn’t know it was ever a Cube. Why would anyone ever want to do this? You’d think at least there’d be some kind of ‘slice’ keyword so that you have to tell the compiler, yes, I really want to do this nonsensical thing. It would keep a lot of people out of trouble, not least of all myself.

This begs for an experiment, though, that may unravel some of the mysteries of &! Here’s my theory. Since object slicing is a thing, then if I have an array of Cubes and I do this:

for (Shape shape : cubes)
{
	// do stuff with shape
}

The cubes will get sliced, and act like Shapes. But if I do this:

for (Shape &shape : cubes)
{
	// do stuff with shape
}

The cubes should not get sliced, and act like Cubes! Because it’s a reference, I’m not actually copying the object! Right?? Do I know my &??

It turns out I do, but there’s an even more bizarre side effect that is, in retrospect, obvious… if you do anything in this for loop (the first one, without the &) that affects the state of the object, it only affects the copy, not the original one in the array! So in that situation the & really is your friend, in many ways.

This is all fascinating, but I’m going back to pointers so that I can have my polymorphism.

Leave a Reply

Your email address will not be published. Required fields are marked *