如何优雅地切片对象

How to elegantly slice the object

所以基本上我有一个 class SomethingSwimming 和一个派生的 class Ship。我想实现的是,在某些情况下,Ship 可能会失去其特殊品质(例如将龙虾扣为人质)并变成另一个 SomethingSwimming 对象。

举例说明:

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;
}

我的问题是如何 crash Ship 使其仅变为 SomethingSwimming(因此它不再是 Ship)而无需重新初始化。

无法在保持基础子对象身份的同时切掉对象的其余部分。您可以创建基本子对象的新副本,并丢弃派生对象。

目前您在 crash 中创建了一个不相关的对象,因此 m_treasures 不会受到先前指向的对象的 m_treasures 的影响。要创建原始基础子对象的副本,您可以这样做:

b = make_shared<SomethingSwimming>(*b);

或者,在调用站点,您可以通过静态调用虚拟成员函数将间接引用的基类视为它不是派生对象的一部分:

a->SomethingSwimming::howManyLobstersOnBoard()

这将导致 m_treasures 的值,而不管对象的最派生类型如何。