【问题标题】:Is downcasting this during construction safe?在施工过程中向下投射是否安全?
【发布时间】:2009-07-28 10:02:46
【问题描述】:

我有一个类层次结构,我知道给定的类 (B) 将始终派生为第二个 (D)。在 B 的构造函数中,如果我确定在整个构造完成之前没有人会尝试使用它,将 this 指针静态转换为 D* 是否安全?就我而言,我想将对该对象的引用传递给另一个类 (A)。

struct A
{
    D & d_;

    A(D & d) : d_(d) {}
};

struct D; //forward declaration

struct B
{
    A a;

    B() : a(std::static_cast<D&>(*this)) {}
};

struct D : public B
{};

这段代码安全吗?

【问题讨论】:

  • 这提出了一个问题,如果 B 总是是 D,那么 D 会添加什么值。
  • B 是类模板,根据其模板参数定义或不定义成员函数。有几个这样的类模板,然后由D继承以提供依赖于模板参数的接口。

标签: c++ inheritance static-cast


【解决方案1】:

我对此一无所知。我很难找到您的代码在安全的情况下不安全的原因:

struct B
{
    A a;

    B(D& d) : a(d) {}
};

struct D : public B
{
    D() : B(*this) {}
};

但我可能仍会使用此处提供的表格。

【讨论】:

  • 这是避免 static_cast 的好方法,但是关于 this 在初始化列表中的有效性问题仍然存在。 +1 以更简洁的方式编写它。
【解决方案2】:

不,不是。 D 的数据成员的构造函数尚未运行。

由于 D 的成员尚未构建,因此 D 尚未完全构建,因此从技术上讲,对 D 的引用应该是无效的。我希望这在大多数实现中都没有问题,但仍然如此。

我想提出一个更好的机制,但我想“更好”很大程度上取决于实际细节。

【讨论】:

  • 我知道 D 还没有被构建,所以我明确指出在构建结束之前不会访问它的任何成员。
  • 关于初始化器列表中 this 指针的有效性,我还记得在某处读到使用它是不安全的,但如果没有成员被访问,它仍然是真的吗?我会尝试在标准中找到可以回答这个问题的段落。
  • 显然,该标准明确规定可以在成员初始化器列表中使用“this”来引用正在构造的对象。
  • 我无法再次挖掘它,但我也无法重现它 - 我认为场景有点不同,可能是在基类中初始化了一个引用到派生类中的成员。无论如何,我正在删除 IIRC 部分,这是一种误导。谢谢,卢克!
【解决方案3】:

@AProgrammer's answer 让我意识到static_cast 可以通过将this 指针从派生类传递给基类来轻松避免。因此,问题归结为 this 指向 member-initializer-list 的指针的有效性。

我在 C++ 标准 [12.6.2.7] 中找到了以下注释:

[注意: 因为 mem-initializer 是在构造函数的范围内计算的,所以 this 指针可以在 expression-list 中使用mem-initializer 来引用正在初始化的对象。 ]

因此,在 member-initializer-list 中使用this 是完全有效的,所以我认为呈现的代码是安全的(只要不访问 D 的成员)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    相关资源
    最近更新 更多