说,代码

    class Derived: public Base {....}

    Base* b_ptr = new( malloc(sizeof(Derived)) ) Base(1);
    b_ptr->f(2);
    Derived* d_ptr = new(b_ptr) Derived(3);
    b_ptr->g(4);
    d_ptr->f(5);

似乎是合理的,并且LSP是满意的。

我怀疑当Base和Derived是POD时,此代码是标准允许的,否则是不允许的(因为vtbl ptr被覆盖)。我的问题的第一部分是:请指出这种覆盖的确切前提。

可能存在其他允许标准重写的方法。

我的问题的第二部分是:还有其他方法吗?他们的确切先决条件是什么?

更新:我不想编写这样的代码;我对这种代码的理论可能性(或可能性)感兴趣。因此,这是“标准纳粹”问题,而不是“我如何...”问题。 (我的问题是否已移至其他stackoverflow网站?)

UPDATE2&4:析构函数如何?该代码的语义是“通过派生实例的切片(破坏性地)更新基本实例”。为了简单起见,让我们假设基类有一个琐碎的析构函数。

UPDATE3:对我来说最有趣的是通过b_ptr->g(4)的访问的有效性

最佳答案

如果b_ptr = d_ptr子对象不在Derived的布局中,则真的需要在Base的新放置之后执行Derived。如所写,b_ptr->g(4)引起未定义的行为。

规则(3.8 basic.life):



您还可能应该在重新使用旧对象之前先销毁旧对象,但是该标准并未对此强制规定。但是,如果不这样做,将泄漏旧对象拥有的所有资源。标准的第3.8节(basic.life)中给出了完整的规则:

10-02 02:36
查看更多