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