基类有时可以初始化派生类的成员吗?

该程序是否具有明确定义的行为?

struct Foo;

struct FooImpl {
  FooImpl();
};

struct Foo : FooImpl {
  int bar;
};

FooImpl::FooImpl() {
  static_cast<Foo *>(this)->bar = 0;
}

int main() {
  return Foo().bar;
}

需要特别注意的是,它Foo::bar是默认初始化的。我知道如果Foo::bar被初始化Foo,这肯定是不好的,因此这个特殊的例子。

请记住,这是一个用于说明案例的简化示例。我对 C++ 规范对此的看法感兴趣(而不是这在风格上是好还是坏的代码)。

回答

一般来说,父母可以访问孩子的成员。就像CRTP一样。

但是,在析构函数和构造函数中访问它们会直接导致 UB。

 FooImpl::FooImpl() 
 {
    static_cast<Foo *>(this)->bar = 0;
 }

这是 UB,因为Foo和 随后bar尚未构建,并且您已经访问它(并修改它!)。同样在析构函数中 - 此时bar已经被删除。相反,您可以使用相同的主体创建Initialize()方法FooImpl并在Foo的构造函数中调用它,那么它就是合法的。


以上是基类有时可以初始化派生类的成员吗?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>