我写C和C++代码已经快二十年了,但这些语言中有一个方面我从未真正理解过。我显然使用了常规的石膏,即。

MyClass *m = (MyClass *)ptr;

到处都是,但似乎有两种其他类型的演员,我不知道有什么不同。以下代码行之间有什么区别?

MyClass *m = (MyClass *)ptr;
MyClass *m = static_cast<MyClass *>(ptr);
MyClass *m = dynamic_cast<MyClass *>(ptr);

当前回答

C样式强制转换合并了const_cast、static_cast和reinterpret_cast。

我希望C++没有C样式转换。C++强制转换非常突出(应该如此;强制转换通常表示做了坏事),并正确区分强制转换执行的不同类型的转换。它们还允许编写类似的函数,例如boost::lexical_cast,从一致性的角度来看,这很不错。

其他回答

你应该看看C++编程/类型转换这篇文章。

它包含对所有不同的转换类型的良好描述。以下内容摘自上述链接:

常量_成本const_cast(expression)const_cast<>()用于添加/删除变量的常量(或易变性)。静态铸造static_cast(表达式)static_cast<>()用于在整数类型。'例如‘char->long,int->short等。静态转换还用于将指针转换为相关类型例如铸造空隙*至适当类型。动态铸造动态转换用于在运行时转换指针和引用,通常用于向上或向下投射指针或引用继承链(继承层次结构)。dynamic_cast(表达式)目标类型必须是指针或引用类型表达式的计算结果必须是指针或引用。动态铸造工程仅当表达式引用的对象类型为与目标类型兼容,并且基类至少有一个虚拟成员函数。如果没有,以及要转换的表达式类型是指针,如果对引用进行动态强制转换,则返回NULL如果失败,将引发bad_cast异常。当它没有失败时,动态强制转换将目标类型的指针或引用返回到对象该表达式引用。重新解释(_C)重新解释强制转换只是将一种类型逐位转换为另一种类型。任意指针或整数类型可以用重新解释的铸造铸造到任何其他类型,容易允许误用。例如,重新解释演员阵容可能会将整数指针强制转换为字符串指针。

静态铸造

staticcast用于您基本上想要反转隐式转换的情况,但有一些限制和添加。staticcast不执行运行时检查。如果您知道您引用的是特定类型的对象,因此不需要进行检查,则应使用此选项。例子:

void func(void *data) {
  // Conversion from MyClass* -> void* is implicit
  MyClass *c = static_cast<MyClass*>(data);
  ...
}

int main() {
  MyClass c;
  start_thread(&func, &c)  // func(&c) will be called
      .join();
}

在本例中,您知道您传递了MyClass对象,因此不需要运行时检查来确保这一点。

动态铸造

dynamic_cast在您不知道对象的动态类型时非常有用。如果引用的对象不包含作为基类转换为的类型,则它将返回空指针(在这种情况下,当您转换为引用时,会引发bad_cast异常)。

if (JumpStm *j = dynamic_cast<JumpStm*>(&stm)) {
  ...
} else if (ExprStm *e = dynamic_cast<ExprStm*>(&stm)) {
  ...
}

如果参数类型不是多态的,则不能使用dynamic_cast进行下变频(转换为派生类)。例如,以下代码无效,因为Base不包含任何虚拟函数:

struct Base { };
struct Derived : Base { };
int main() {
  Derived d; Base *b = &d;
  dynamic_cast<Derived*>(b); // Invalid
}

“向上转换”(向基类转换)对于static_cast和dynamic_cast始终有效,而且也没有任何转换,因为“向上”是隐式转换(假设基类是可访问的,即它是公共继承)。

常规铸造

这些造型也称为C型造型。C风格的强制转换基本上与尝试一系列C++强制转换序列相同,并采用第一个有效的C++强制转换,而不考虑dynamic_cast。不用说,这是更强大的,因为它结合了const_cast、static_cast和reinterpret_cast,但它也不安全,因为它不使用dynamic_cast。

此外,C样式转换不仅允许您这样做,而且还允许您安全地转换到私有基类,而“等效”的static_cast序列会给您带来编译时错误。

有些人更喜欢C风格的演员,因为他们简洁。我只将它们用于数字强制转换,当涉及用户定义的类型时,使用适当的C++强制转换,因为它们提供了更严格的检查。

C样式强制转换合并了const_cast、static_cast和reinterpret_cast。

我希望C++没有C样式转换。C++强制转换非常突出(应该如此;强制转换通常表示做了坏事),并正确区分强制转换执行的不同类型的转换。它们还允许编写类似的函数,例如boost::lexical_cast,从一致性的角度来看,这很不错。

仅供参考,我相信Bjarne Stroustrup曾说过,应该避免C风格的强制转换,如果可能的话,应该使用static_cast或dynamic_cast。

Barne Stroustrup的C++风格常见问题解答

你愿意接受那个建议吗。我远非C++大师。

避免使用C样式转换。

C样式转换是常量转换和重新解释转换的混合,很难在代码中找到和替换。C++应用程序程序员应该避免C样式转换。