Question: I'm a Java programmer and recently started studying C++. I'm confused by something.

I understand that in C++, to achieve polymorphic behavior you have to use either pointers or references. For example, consider a class `Shape` with an implemented method `getArea()`. It has several subclasses, each overriding getArea() differently. Than consider the following function:

```
void printArea(Shape* shape){
    cout << shape->getArea();
}

```

The function calls the correct `getArea()` implementation, based on the concrete `Shape` the pointer points to.

This works the same:

```
void printArea(Shape& shape){
    cout << shape.getArea();
}

```

However, the following method does not work polymorphicaly:

```
void printArea(Shape shape){
    cout << shape.getArea();
}

```

Doesn't matter what concrete kind of `Shape` is passed in the function, the same `getArea()` implementation is called: the default one in `Shape`.

I want to understand the technical reasoning behind this. Why does polymorphism work with pointers and references, but not with normal variables? (And I suppose this is true not only for function parameters, but for anything).

Please explain the technical reasons for this behavior, to help me understand.

Answer: 
The answer is copy semantics.

When you pass an object by value in C++, e.g. `printArea(Shape shape)` a copy is made of the object you pass. And if you pass a derived class to this function, all that's copied is the base class `Shape`. If you think about it, there's no way the compiler could do anything else.

```
Shape shapeCopy = circle;

```

`shapeCopy` was declared as a `Shape`, not a `Circle`, so all the compiler can do is construct a copy of the `Shape` part of the object.
Basically, when you pass an object by value it's copied to an object of the destination type - at that point it *is* an object of the destination type, so there's nothing to polymorph (is that even a word?).

To use your example, `void printArea(Shape shape);`, inside the `printArea()` function the parameter `shape` *is* a `Shape` object, regardless of what object was used at the call site.