为什么只有 static_cast 能够 return 请求类型的新对象?

Why is only static_cast able to return new object of requested type?

在static_cast、dynamic_cast、reinterpret_cast和const_cast中,只有static_cast能够return一个理想类型的对象,而另一种类型只能 return 指针或对表示的引用。为什么会这样?

示例:

int y = 3;
double z = reinterpret_cast<double> (y);//error
double z = reinterpret_cast<double&> (y);//ok
double z = static_cast<double> (y);//but this is ok!!!

const int y = 3;
int z = const_cast<int> (y);//error
int z = const_cast<int&> (y);//ok

和 dynamic_cast:

using namespace std;

class Gun
{
public:
    virtual void shoot(){
        cout << "BANG!\n";
    }
};

class MachineGun : public Gun{
public:
    void shoot() override{
        cout <<"3X-BANG\n";
    }
};

int main()
{
    Gun gun;
    MachineGun tt;
    Gun* gunp = &gun;
    Gun* gunp1 = &tt;

    Gun* newGun = dynamic_cast<Gun*>(gunp1);//ok
    Gun newGun1 = dynamic_cast<Gun>(tt);//error
}

Only static_cast is able to return an object of desirable type

这是不正确的。当转换目标是对象类型时,所有转换 return 一个对象。

也就是说:

  • const_cast 目标只能是一个引用,指向对象的指针或指向成员的指针。这是因为其他类型不是复合类型,其“内部”类型的 cv 限定符可以修改。
  • dynamic_cast 目标只能是对象的引用或指针。没有间接就不能拥有多态性。引用和指针是 C++ 中存在的间接形式。

我正在尝试根据示例进行解释,作为对确实解释演员表性质的其他答案的补充。

int y = 3;
double z = reinterpret_cast<double> (y);//error

这不是 11 种允许的转换之一,reinterpret_cast. Also std::bit_cast 不能在大多数平台上转换它,因为 int 通常没有足够的位用于 double。所以不确定你想要实现什么。

double z = reinterpret_cast<double&> (y);//ok

这出现在有效列表 reinterpret_cast 中,但可能会导致未定义的行为,原因与 std::bit_cast 拒绝的原因相同。在典型的实现中,您的 zy 大,因此占用的位超出了 y 的内存位置。在这些地方更喜欢 std::bit_cast 不会编译为未定义行为但拒绝编译。

double z = static_cast<double> (y);//but this is ok!!!

但这是完全正确的。它实际上与

相同
double z = y;

编译器甚至不会对后者发出警告。但是,当 y 的值范围不完全适合 z 时,则不清楚是否是故意的。在这种情况下,最好使用 former 来表示意图。

const int y = 3;
int z = const_cast<int> (y);//error

很好。荒唐const_cast 编译不通过!或者您尝试实现的效果与更具可读性的效果有何不同

int z = y;

我会写的。请描述你会写前者的情况。

int z = const_cast<int&> (y);//ok

有效,但与以前一样不需要且令人困惑。我只会在这种情况下使用 const_cast

int x;
const int& y = x;
int& z = const_cast<int&> (y);
z = 42;

这里我知道引用 const y 的东西本来就不是 const ,所以将它修改为 42 不是未定义的行为。

关于dynamic_cast你的例子根本没有意义:

Gun newGun1 = dynamic_cast<Gun>(tt);//error

它可能正在尝试做类似的事情:

Gun newGun1 = tt;

即编译。然而,newGun1 的结果是用 MachineGun tt 的切片 Gun 基础子对象初始化的,这通常是编程错误。但是,您尝试通过演员表实现的目标仍然是完全黑暗的。

也许一个简短(令人难忘)的答案是 static_cast 可以采用没有引用(也没有指针)的类型,因为它是唯一可以调用目标类型的构造函数的类型转换。

如有错误请指正