Example: Using Our Petting Zoo
Revisiting Our engaegWith()
Function
Now we can update our
engageWith()
function to take a reference to anAnimal
:
void engageWith(Animal animal) {
animal.speak();
animal.feed();
}
int main() {
Cow bessie("Bessie");
Raptor peri("Peri");
std::cout << "# Petting the Cow:" << std::endl;
engageWith(bessie);
std::cout << "\n# Petting the Raptor:" << std::endl;
engageWith(peri);
return 0;
}
This is great. It's totally going to print
## Petting the Cow: Bessie says: Mooooo Bessie eats ## Petting the Raptor: Peri says: Rawrrr Peri eats
Run the code yourself and see what happens:
The output looks like
# Petting the Cow:
Bessie makes nonspecific animal noises
Bessie eats
# Petting the Raptor:
Peri makes nonspecific animal noises
Peri eats
Hay! Why didn't the
Cow
moo? Why didn't theRaptor
rawr?I think I see something!
Oh?
engageWith()
is taking its argument as a copy, right?It is.
So when the copy is made, the compiler is only copying the
Animal
parts to make a newAnimal
object that doesn't have thehappiness_
oranger_
data members, so it literally isn't aCow
orRaptor
, it's just anAnimal
.That's right! Because
engageWith()
takes anAnimal
by value, it only copies the commonAnimal
parts of ourCow
orRaptor
objects to make theAnimal
copy.FWIW, this process is sometimes called “slicing”, as we've sliced away the
Cow
- orRaptor
-specific parts to be left with a plain genericAnimal
.I bet if we change it to take a reference, things will be better.
Let's try that!
Either edit the code to add the ampersand, or run this updated version.
Noooooooooo!
How did that not fix it??
Hang tight. We can totally figure out a way to make this petting zoo of
Cow
s andRaptor
s work.Again I ask, can or should?
Things are, in fact, working exactly as Duck said they should on the Before You Start page.
Specifically, Duck said that when figuring out what function to call, we should use the type of the variable.
In this case, our code looks like
void engageWith(Animal& animal) {
animal.speak();
animal.feed();
}
The type of animal
is Animal
, so, as promised, we call Animal::speak
.
So C++ is doing exactly what you wanted.
Uh…
Watch what you wish for.
It turns out that we don't want to decide what function to call based on the (static) type at compile time (
Animal
)—we really want to decide based on the actual object we have at runtime (Cow
orRaptor
).C++ can do that, too. If you ask for it.
Tell me MORE!
(When logged in, completion status appears here.)