首页 > 解决方案 > 为什么在类型转换的 nullptr 上不会发生隐式转换

问题描述

当我遇到意想不到的事情时,我试图找到一种静态断言派生类指针可以安全地重新解释为指向基类的指针的方法:

我预计以下代码中的两个静态断言会失败。

class Base1 {
    int x;
};
class Base2 {
    int y;
};
class Derived : public Base1, public Base2 {
    int z;
};

// one of these should fail???
static_assert( (Derived *)nullptr == (Base1 *)nullptr, "err1" );
static_assert( (Derived *)nullptr == (Base2 *)nullptr, "err2" );
// and one of these as well???
static_assert( (Base1 *)(Derived *)nullptr == nullptr, "err3" );
static_assert( (Base2 *)(Derived *)nullptr == nullptr, "err3" );

对于第一对断言,由于它的参数是类型Derived*Base1*/ Base2*,我本来希望Derived*将隐式转换为 a Base1*orBase2*进行比较。由于Base1Base2不能占用相同的内存,它们不能都位于Derived对象占用的内存的开头,因此这些转换之一应该增加了指针值。然后不应该发现非零指针等于空。

同样,对于第二对,我希望显式转换为Base1*并且Base2*应该更改其中一个指针,但它们仍然比较等于 null。

这里发生了什么?

标签: c++multiple-inheritancestatic-assert

解决方案


空指针始终是空指针,并且它始终是空指针。

[conv.ptr](强调我的)

3 “指向 cv 的指针D”类型的纯右值,其中D是类类型,可以转换为“指向 cv 的指针B”类型的纯右值,其中 B是 的基类D。如果B是 的一个不可访问或模棱两可的基类D,则需要进行此转换的程序格式错误。转换的结果是指向派生类对象的基类子对象的指针。空指针值转换为目标类型的空指针值

由于将 aDerived*与 a进行比较Base*需要将它们转换为通用类型,因此这就是将要发生的转换。如您所见,它保留了空值。

这样做的基本原理是不可能从空指针值产生一个看起来有效的值。如果您从空指针值开始,您将继续使用它。


推荐阅读