这是不确定的吗?

Is this downcasting undefined?

考虑这个例子,其中基础 class 有一些数据成员,而派生的只提供了一个额外的方法:

struct TestBase
{
    int x;
    TestBase() : x(5) {}
};

struct TestDerived : public TestBase
{
    void myMethod()
    {
        x=8;
    }
};

int main()
{
    TestBase b;
    TestDerived& d=static_cast<TestDerived&>(b);
    d.myMethod();
}

这是向下转换为错误的类型,所以据我所知它有未定义的行为。但是对于这种情况,是否可能存在一些例外情况,其中派生的 class' 布局与基础 class 的布局相同?

如果您尝试在不兼容的类型之间进行转换,

static_cast<> 将生成编译器错误,但它无法在编译时或运行时保证转换有效。

由于 TestDerived 继承自 TestBase,因此它是 合法的 转换static_cast 运算符,但并非所有向下转换都必然是 安全的演员表。

在上面的代码中,恰好 安全地工作 - 很可能是因为 TestMethod 只访问基础 class 成员,是单一继承,没有 vtables,并且不是做任何复杂的事情。因此,编译器 可能 将转换视为无操作的简单示例。其他人会告诉您 "this is undefined behavior" - 不要对这样编写的代码做出任何假设。 (他们也是正确的。)

来自标准(强调我的):

§5.2.9 Static cast [expr.static.cast] ...

(2) An lvalue of type “cv1 B,” where B is a class type, can be cast to type “reference to cv2 D,” where D is a class derived from B, if a valid standard conversion from “pointer to D” to “pointer to B” exists, cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is neither a virtual base class of D nor a base class of a virtual base class of D. The result has type “cv2 D.” An xvalue of type “cv1 B”may be cast to type “rvalue reference to cv2 D” with the same constraints as for an lvalue of type “cv1 B.” If the object of type “cv1 B” is actually a subobject of an object of type D, the result refers to the enclosing object of type D. Otherwise, the behavior is undefined.

我的第一个猜测是在这种情况下转换应该是有效的, 因为我对术语 subobject.

感到困惑

现在(感谢@T.C。和@M.M),很明显行为在这种情况下是未定义的

强制转换在以下示例中有效:

int main()
{
    TestDerived d;
    TestBase &br = d; // reference to a subobject of d
    TestDerived &dr = static_cast<TestDerived&>(br);  // reference to the original d object
    d.myMethod();
}

此处,class TestDerived (d) 的对象将具有 class TestBase (br 的子对象引用此对象)。