Search code examples
c++object-slicing

How to elegantly slice the object


So basically I have a class SomethingSwimming and a derived class Ship. I want to implement that upon some event a Ship may lose its special qualities (such as holding lobsters hostage) and become just another SomethingSwimming object.

To illustrate:

class SomethingSwimming
{
    protected:
    int m_treasures;

    public:
    SomethingSwimming(int treasures): m_treasures(treasures) {;}
    virtual int howManyLobstersOnBoard() {return 0; }
};

class Ship: public SomethingSwimming
{
    protected:
    int m_lobstersOnBoard;

 public:
    Ship(int treasures, int lobstersOnBoard): SomethingSwimming(treasures), m_lobstersOnBoard(lobstersOnBoard) {;}
    int howManyLobstersOnBoard() {return m_lobstersOnBoard; }
};

void crash(shared_ptr<SomethingSwimming>& b)
{
    b = make_shared<SomethingSwimming>(100);
}

int main()
{
    shared_ptr<SomethingSwimming> a = make_shared<Ship>(100, 12);

    cout << "How many lobsters on board: " << a->howManyLobstersOnBoard() << endl;

    crash(a);

    cout << "How many lobsters on board: " << a->howManyLobstersOnBoard() << endl;

    return 0;
}

My question is how to crash the Ship so it becomes only SomethingSwimming (so it's not a Ship anymore) without reinitializing.


Solution

  • There is no way of cutting away rest of the object while keeping the identity of the base sub object. You can make a new copy of the base sub object, and throw away the derived object.

    Currently you create an unrelated object in crash and thereby m_treasures won't be affected by m_treasures of the previously pointed object. To create a copy of the original base sub object, you can do:

    b = make_shared<SomethingSwimming>(*b);
    

    Alternatively, at the call site you can treat an indirectly referred base as if it were not part of a derived object by calling virtual member functions statically:

    a->SomethingSwimming::howManyLobstersOnBoard()
    

    This will result in the value of m_treasures regardless of the most derived type of the object.