考虑这个例子,其中基类有一些数据成员,而派生类只提供了一个额外的方法:
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();
}
这是向下错误的类型,所以AFAIU它有未定义的行为。但是,对于这样的情况,可能存在一些例外情况,即派生类&#39;布局与基类相同?
答案 0 :(得分:8)
从标准(强调我的):
§5.2.9静态演员[expr.static.cast] ......
(2)类型为“cv1 B”的左值,其中B是类类型, 可以强制转换为“引用cv2 D”,在哪里 D是从B 派生的类,如果有效 存在从“指针D”到“指针B”的标准转换,cv2是 与cv1和B相同的cv资格,或更高的cv资格 既不是D的虚基类,也不是虚基的基类 D类。结果类型为“cv2 D”。类型为“cv1 B”的x值可以是 使用相同的约束来强制转换为“对cv2 D的rvalue引用” 一个类型为“cv1 B”的左值。 如果“cv1 B”类型的对象实际上是对象的子对象 类型D,结果指的是类型为D的封闭对象。 否则,行为未定义。
我的第一个猜测是演员应该在这种情况下有效, 因为我对术语子对象感到困惑。
现在(感谢@ 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();
}
此处,类TestDerived
(d
)的对象将具有类TestBase
的子对象(br
是对此对象的引用)。
答案 1 :(得分:-1)
{{1}}将生成编译器错误,但它不能保证在编译时或运行时转换有效。
由于TestDerived继承自TestBase,因此在static_cast运算符允许的情况下进行 legal 转换,但并非所有向下转换都必须是安全强制转换。
在上面的代码中,恰好安全地工作 - 很可能是因为TestMethod只访问基类成员,是单继承,没有vtable,也没有做任何复杂的事情。因此,编译器可能将转换视为无操作的简单示例。其他人会告诉你&#34;这是未定义的行为&#34; - 而不是假设任何关于这样写的代码。 (而且他们也是正确的。)