Reputation:
Consider the following code:
class A {
public:
virtual ~A() { }
virtual void print() const {
std::cout << "In A" << std::endl;
}
};
class B : public A {
public:
B() { }
virtual ~B() { }
virtual void print() const {
std::cout << "In B" << std::endl;
}
};
void doSomething(A* a) {
a->print();
}
void doSomething(const A a) {
a.print();
}
int main()
{
A* a = new B();
doSomething(a);
doSomething(B());
return 0;
}
Why does this output:
In B
In A
But when you change doSomething
to doSomething(const A& a)
it outputs:
In B
In B
Upvotes: 7
Views: 6522
Reputation: 254431
This is known as slicing.
When passing A
by value, a local copy is made, by copying just the A
part of the caller's object. Since this has both a static and dynamic type of A
, that's the override of print
that's chosen.
Passing by reference, the function gets a reference to the caller's object with dynamic type B
, so that override is chosen.
Using abstract base classes can prevent confusing behaviour like this - they can't be directly instantiated, and so can't be passed by value.
Upvotes: 12