Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does passing by reference always avoid the slicing issue?

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?

like image 654
Anthony Avatar asked Nov 26 '11 13:11

Anthony


3 Answers

"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.

like image 89
Kerrek SB Avatar answered Oct 26 '22 08:10

Kerrek SB


The behavior you are seeing is correct. This is how it is supposed to work. References work just like pointers.

like image 24
trenki Avatar answered Oct 26 '22 08:10

trenki


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.

like image 3
Nathan Monteleone Avatar answered Oct 26 '22 07:10

Nathan Monteleone