内部交换子类型的范例

时间:2018-11-13 22:12:38

标签: c++ inheritance types polymorphism siblings

假设我有这个:

struct Base {
    virtual void swap();
    Expensive mem;
};

struct Left : Base {
    void swap() override;
};

struct Right : Base {
    void swap() override;
};

给出一个包含vector<shared_ptr<Base>> fooLeft对象的Right。可以说元素13是Left,现在我希望它是Right。我可以做类似的事情:

foo[13] = make_shared<Right>();

但是现在让我们假设Expensive的构建或复制非常昂贵,并且假设LeftRight不包含自己的成员,它们只是一种不同的处理方式操纵和解释mem。有没有办法我可以强制或告诉元素13它现在是Right而又不破坏那里的Left?我是否可以使用enable_shared_from_this或类似的方法将销毁和重建操作到我可以称之为foo[13].swap()的地方,它将“变成” Right

1 个答案:

答案 0 :(得分:2)

好吧,您可以考虑将LeftRight设为相同的类型。但是,如果您不能做到这一点,那么您仍然可以利用移动语义。假设Expensive的价格便宜。然后您可以执行以下操作:

struct Base {
    Base(Expensive mem) : mem(std::move(mem)) {}
    virtual std::shared_ptr<Base> swap() = 0;
    Expensive mem;
};
struct Left : Base {
    Left(Expensive mem) : Base(std::move(mem)) {}
    std::shared_ptr<Base> swap() override;
};
struct Right : Base {
    Right(Expensive mem) : Base(std::move(mem)) {}
    std::shared_ptr<Base> swap() override;
};
std::shared_ptr<Base> Left::swap() {
    return std::make_shared<Right>(std::move(mem));
}
std::shared_ptr<Base> Right::swap() {
    return std::make_shared<Left>(std::move(mem));
}
// ...
foo[13] = foo[13]->swap();

(请注意,在输入foo[13]的主体之前,std::shared_ptr<Base>::operator=所指向的原始对象不会被破坏,此时swap()将完成并离开{{ 1}}处于可破坏状态,因此在我看来这段代码是定义明确的。)