This surprised me a little bit, but I was playing around with some code and found out that, at least on my computer, when a function accepts a parent class by reference and you pass a child instance, that the slicing problem doesn't occur. To illustrate:
#include <iostream>
class Parent
{
public:
virtual void doSomething()
{
using namespace std;
cout << "Parent::DoSomething" << endl;
}
};
class Child : public Parent
{
public:
virtual void doSomething()
{
using namespace std;
cout << "Child::DoSomething" << endl;
}
};
void performSomething(Parent& parent)
{
parent.doSomething();
}
int main(int argc, char** argv)
{
Child myChild;
performSomething(myChild);
return 0;
}
This prints out Child::DoSomething
.
Like I said, I was a little surprised. I mean, I know that passing by reference is like passing pointers around (but much safer in my understanding), but I didn't know I still got to keep polymorphic goodness when doing so.
I just want to make sure, is this supposed to happen or is it one of those "it works on my machine" type of instances?
"Slicing" refers to the inability of the base copy constructor to distinguish exact type matches from derived classes. The only way to invoke slicing is to invoke the base copy constructor. Typically this occurs when passing arguments by value, though other situations can be contrived:
class Base { };
class Derived : public Base { };
void foo(Base);
int main()
{
Derived x;
Base y = x; // flagrant slicing
foo(x); // slicing by passing by value
}
You're never doing any such thing, so you do not encounter any slicing situations.
The behavior you are seeing is correct. This is how it is supposed to work. References work just like pointers.
That's supposed to happen. Passing by reference is EXACTLY like passing pointers -- it's doing the same thing under the hood. There's no magic to this; every instance of a polymorphic object has a virtual function table associated with it. As long as you don't copy anything, you're not going to lose that information and your virtual function calls will work the way you expect they would.
The reason that you run into problems when passing by value is that it will use the copy constructor of the type you specified in the function signature, so you end up with an entirely new instance of the superclass.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With