const_cast和C风格的强制类型转换(ObjectType)之间是否存在实际差异?
const_cast
传达了一种C风格转换所不能表达的转换意图。
如果您误用const_cast
进行除添加或移除const
或volatile
之外的其他用途,则编译器会通过错误消息帮助您。
此外,const_cast
是可搜索的,而C风格转换不可。
const_cast
只能添加或移除 const
(或者 volatile
,虽然这种情况很少出现)。
C 风格的转换可以像任何“新”的转换一样执行相同的操作,除了 dynamic_cast
(它可以执行一些其他转换无法执行的操作,但这在此处并不重要)。
C++中的C风格转换尝试进行静态转换、重新解释转换、常量转换或这些转换的组合。
建议避免使用C转换,主要原因是...
C
强制类型转换比其他组合方式更加强大。在某些边缘情况下,唯一的选择是使用 C 风格的强制类型转换(例如向私有基类进行上转型),尽管可以争论你不应该编写那样的代码... - David Rodríguez - dribeasreinterpret_cast
通常适用于单一继承。对于多重继承,它通常适用于一个基类,但对于其他所有基类都会失败(只有一个基类可以位于派生对象的开头)。 - Jerry Coffinstatic_cast
。考虑 struct D : A, B, private C {} d;
,(void*)(C*)&d
和 (void*)reinterpret_cast<C*>(&d)
的输出将不同。在C转换的情况下,指针将引用实际的C
子对象,而在reinterpret_cast
的情况下,它将(很可能,标准不保证)引用D
对象(或第一个基类)的位置。 - David Rodríguez - dribeasconst_cast
只能修改参数的 常量性(或 易变性),而不能修改其 基本 类型。因此
const T *tc = f();
volatile T *tv = g();
U *ua = const_cast<U*>(tc); //error
U *ub = const_cast<U*>(tv); //error
U *ub = (U*)(tc); //okay
U *ub = (U*)(tv); //okay
因此,C风格的转换可以修改带有cv限定符的T*
为U*
而不会出现任何问题。
同样的操作。C风格的转换可以将const全部去除。
使用const_cast的原因是它可以作为可搜索的红旗,用于搜索并仔细审查/惩罚有罪者。这个想法是,C++比C更加类型严格。因此,如果故意违反类型系统(例如违反const正确性),即使不是不可能,也很容易被发现。
使这种类型安全违规完全不可能会破坏太多的向后兼容性。
const_cast更为受限,除了更改常量性以外,不允许您执行任何其他操作。这使它更安全,即更少出现意外。
此外,它更易于搜索。