Q1。为什么将 NULL 指针与 static_cast
一起使用会导致崩溃,而 dynamic_cast
和 reinterpret_cast
会返回一个 NULL 指针?
问题发生在类似于下面给出的方法中:
void A::SetEntity(B* pEntity, int iMyEntityType)
{
switch (iMyEntityType)
{
case ENTITY1:
{
Set1(static_cast<C*>(pEntity));
return;
}
case ENTITY2:
{
Set2(static_cast<D*>(pEntity));
return;
}
case ENTITY3:
{
Set3(static_cast<E*>(pEntity));
return;
}
}
}
Inheritance:
class X: public B
class Y: public B
class Z: public B
class C: public X, public M
class D: public Y, public M
class E: public Z, public M
Q2。 static_casting
从 B 到 C/D/E 是否有效? (这工作正常,直到输入变为 NULL)
我正在使用 gcc 版本 3.4.3
原文由 Gayan 发布,翻译遵循 CC BY-SA 4.0 许可协议
你用的是什么编译器?从基类型到派生类型的静态转换可能会导致对指针的调整 - 特别是在涉及多重继承的情况下(根据您的描述,情况似乎并非如此)。但是,如果没有 MI,它仍然是可能的。
该标准表明,如果正在转换空指针值,则结果将是空指针值(5.2.9⁄8 静态转换)。但是,我认为在许多编译器上,大多数向下转换(尤其是在涉及单继承时)不会导致指针调整,所以我可以想象编译器可能有一个错误,它不会对 null 进行特殊检查这将需要避免将零值空指针“转换”为一些非零值无意义的指针。我假设要存在这样的错误,您必须做一些不寻常的事情来让编译器不得不调整向下转换中的指针。
看看为您的示例生成了什么样的汇编代码可能会很有趣。
有关编译器如何布局可能需要使用静态转换进行指针调整的对象的详细信息, Stan Lippman 的“C++ 对象模型内部” 是一个很好的资源。
Stroustrup 关于 C++ 的多重继承的论文(从 1989 年开始)也是一本不错的读物。如果 C++ 编译器有我推测的错误,那就太糟糕了 - Stroustrup 在那篇论文中明确讨论了空指针问题(4.5 零值指针)。
对于你的第二个问题:
这是完全有效的,只要当您将 B 指针转换为 C/D/E 指针时,B 指针实际上指向 C/D/E 对象的 B 子对象(分别)并且 B 不是不是虚拟基地。这在标准的同一段落(5.2.9⁄8 Static cast)中有所提及。我强调了与您的问题最相关的段落中的句子:
最后,您可以使用以下方法解决问题:
这就是编译器应该为你做的。