说,代码
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
)中给出了完整的规则: