这是未定义的下转换吗
Is this downcasting undefined?
考虑这个例子,基类有一些数据成员,而派生类只提供了一个额外的方法:
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有未定义的行为。但是,在这种情况下,派生类的布局与基类的布局相同,可能会有一些例外吗?
来自标准(强调矿):
§5.2.9静态铸造[expr.Static.cast]…
(2) 类型为"cv1B"的左值,其中B是类类型,可以强制转换为类型"reference to cv2 D",其中D是从B派生的类,如果存在从"指针到D"到"指针到B"的标准转换,cv2为与cv1和B相同或更高的cv资格既不是D的虚拟基类,也不是虚拟基类的基类D的类。结果的类型为"cv2 D"。类型为"cv1 B"的xvalue可能为强制转换为类型"对cv2D的右值引用",具有与类型为"cv1B"的左值如果类型为"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
是对该对象的引用)。
static_cast<>
将生成编译器错误,但它不能保证在编译时或运行时强制转换有效。
由于TestDerived继承自TestBase,因此它是static_cast运算符允许的合法强制转换,但并非所有向下转换都必须是安全的强制转换。
在上面的代码中,它只是碰巧安全地工作——很可能是因为TestMethod只访问基类成员,是单一继承,没有vtables,并且不做任何复杂的事情。因此,编译器很可能将强制转换视为一个无操作的简单示例。其他人会告诉你"这是未定义的行为"——不要对这样写的代码抱有任何假设。(它们也是正确的。)
- 为什么从 char 转换为 std::byte 可能是未定义的行为?
- 将结构 std::memcpy 转换为具有足够容量的 std::vector 是未定义的行为<char>吗?
- 在C++中,转换为simd类型是否有未定义的行为
- ROS中未定义的参考误差到OpenCV图像转换器
- 强制转换为指针引用是否会导致未定义的行为
- 如果没有未定义的行为 [c++],哪些浮点值无法转换为 int?
- 使用 char16_t 类型作为 char[] 数组,并通过 reinterpret_cast<> 重新转换它。我的代码是否有未定义的行为?
- 使用没有显式强制转换的常量调用未定义的行为
- 自定义强制转换未应用于派生类的引用
- 将项目转换为 qt5 并将未定义的引用转换为 'vtable for qt5 和 cmake
- 仅更改常量性的指针强制转换是否可以调用未定义的行为
- 编译器如何优化不正确C++分层向下转换以导致真正的未定义行为
- 强制转换包含多态类型的模板时的未定义行为
- 将函数地址转换为 64 位整数:未定义/行为不当
- 如何将任意双精度转换为整数,同时避免未定义的行为
- 这是未定义的下转换吗
- 在指针到 T、T 数组和指针到 T 数组之间转换的行为始终未定义
- 类型之间的指针强制转换和未定义行为
- .mm转换导致架构i386错误的未定义符号
- 调用从不兼容类型强制转换的零数据结构的成员函数-未定义