c++ - 需要澄清 C 风格、重新解释和 const 转换

标签 c++ casting reinterpret-cast const-cast

我假设 C 风格的转换(不鼓励)只是 reinterpret_casts 是对的吗?使用后者在寻找令人讨厌的转换时在视觉上引人注目并且易于搜索,因此推荐使用 C 风格转换?

如果使用 const_cast 放弃 const 并写入原始 const 对象是未定义的,那么 const_cast 的目的是什么?

注意:我知道 Bjarne 正确地谴责转换操作是不安全的,甚至达到了声明“丑陋 操作应该具有丑陋语法形式的程度。 “因此 C++ 中转换运算符的冗长。所以我会尽量减少它们的使用。 promise 。 :)

最佳答案

没有。 C 转换可以执行与 const_caststatic_castreinterpret_cast 或其组合等效的操作。如果这还不够,它还可以做至少一个小技巧,没有较新的类型转换组合根本做不到!

如果原始变量的定义没有const,您可以使用const_cast 定义结果,但您所拥有的只是一个const 指针或引用到那个对象。 OTOH,如果您认为您有充分的理由使用 const_cast,那么您可能真的应该查找 mutable

编辑:我想我应该马上说出来,但是 C 风格的转换可以转换为不可访问的基类。例如,考虑如下内容:

[编辑:我正在将代码更新为可以编译并(通常)演示问题的代码。 ]

#include <iostream>

class base1 {
public:
    virtual void print() { std::cout << "base 1\n"; }
};

class base2 {
public:
   virtual void print() { std::cout << "base 2\n"; }
};

class derived : base1, base2 {}; // note: private inheritance

int main() {    
    derived *d = new derived;
    base1 *b1 = (base1 *)d;    // allowed
    b1->print();    // prints "base 1"
    base2 *b2 = (base2 *)d;    // also allowed
    b2->print();    // prints "base 2"

//    base1 *bb1 = static_cast<base *>(d);  // not allowed: base is inaccessible

    // Using `reinterpret_cast` allows the code to compile.
    // Unfortunately the result is different, and normally won't work. 
    base1 *bb2 = reinterpret_cast<base1 *>(d);
    bb2->print();   // may cause nasal demons.

    base2 *bb3 = reinterpret_cast<base2 *>(d); 
    bb3->print();   // likewise
    return 0;
}

使用reinterpret_cast 的代码将编译——但尝试使用结果(至少两者之一)将导致严重问题。 reinterpret_cast 获取派生对象的 base 地址并尝试将其视为指定类型的基对象——并且因为(至多)一个基对象实际上可以存在于该地址,试图将其视为另一个地址可能/将导致重大问题。编辑:在这种情况下,除了它们打印的内容外,这些类基本上是相同的,因此尽管可能发生任何事情,但对于大多数编译器来说,最后两个都将打印出“base 1”。 reinterpret_cast 获取该地址处的任何内容,并尝试将其用作指定类型。在这种情况下,我(试图)让它做一些无害但可见的事情。在实际代码中,结果可能不会那么漂亮。

如果代码使用公共(public)继承而不是私有(private)继承,C 风格的转换将像 static_cast 一样工作——即它知道派生类中每个基类对象“存在”的位置,并调整结果,因此每个结果指针将起作用,因为它已被调整为指向正确的位置。

关于c++ - 需要澄清 C 风格、重新解释和 const 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2346616/

相关文章:

c++ - 如何在装饰器模式实现中正确使用 shared_ptr?

java - 如何在 java 中使用泛型来对对象执行相当于强制转换的操作?

c++ - 使用 reinterpret_cast 将文件读入结构

python - 如何忽略 SIGKILL 或强制进程进入 'D' sleep 状态?

c++ - 具有构造函数的单链表类

c++ - 如果构建和销毁了许多 vector<T> ,自定义分配器是否会提高性能?

C++ 子类化、继承和转换

rust - 选项类型的类型转换

c++ - 调用从不兼容类型转换而来的零数据结构的成员函数 - 未定义?

C++11:将结构数组重新解释为结构成员数组