Polymorphism and Slicing with references

156 Views Asked by At

I didn't fully understand object slicing in C++. With the following example code two objects seem to receive the same processing, but polymorphism works for only one of them.

I'm using references and one of the objects doesn't seem to be sliced. I believe something must happen during the launch_ship function call, but I don't know exactly what is going wrong.

Here is the example code.

#include <iostream>


class SpaceShip
{};

class MilleniumFalcon: public SpaceShip
{};

class Pilot
{
public:
     virtual void operate(SpaceShip&)
    {
        std::cerr << "Operating spaceship" << std::endl;
    }

    virtual void operate(MilleniumFalcon&)
    {
        std::cerr << "Cannot operate that spaceship!" << std::endl;
    }
};

class Chewbacca: public Pilot
{
public:
    virtual void operate(SpaceShip&)
    {

        std::cerr << "Don't want to operate that low spaceship!" <<
                  std::endl;
    }

    virtual void operate(MilleniumFalcon&)
    {
         std::cerr << "Operating the Millenium Falcon" << std::endl;
    }
};

void launch_ship(Pilot& pilot, SpaceShip& ship)
{
      pilot.operate(ship);
}

int main()
{
    Chewbacca chewie;
    MilleniumFalcon millenium;

    launch_ship(chewie, millenium);
}

output : Don't want to operate that low spaceship!

1

There are 1 best solutions below

0
On BEST ANSWER

There are no slicing here.

C++ uses single dispatch and not multiple dispatch.

The dispatch done by virtual is done only with this instance.

so in

pilot.operate(ship);

there is only a dispatch with pilot (and use dynamic type of pilot), but we use static type of ship (so SpaceShip&)

You have to use visitor or implement yourself a multiple dispatch.

For example:

class SpaceShip
{
public:
    virtual void operate_by(Pilot& pilot) { pilot.operate(*this); }
};

class MilleniumFalcon: public SpaceShip
{
public:
    virtual void operate_by(Pilot& pilot) override { pilot.operate(*this); }
};


void launch_ship(Pilot& pilot, SpaceShip& ship)
{
    ship.operate_by(pilot);
}

Demo