如何优雅地切片对象

时间:2018-10-27 13:13:29

标签: c++ object-slicing

所以基本上我有一个类SomethingSwimming和一个派生类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)而无需重新初始化。

1 个答案:

答案 0 :(得分:2)

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

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

b = make_shared<SomethingSwimming>(*b);

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

a->SomethingSwimming::howManyLobstersOnBoard()

这将导致m_treasures的值,而与对象的最派生类型无关。