我听说static_cast函数应该优于c风格或简单函数风格的强制转换。这是真的吗?为什么?


当前回答

主要原因是经典的C强制转换不区分static_cast<>()、reinterpret_cast<>()、const_cast<>()和dynamic_cast<>()。这四件事是完全不同的。

static_cast<>()通常是安全的。语言中存在有效的转换,或者有适当的构造函数使转换成为可能。唯一有点风险的时候是当你向下转换到一个继承类的时候;您必须确保对象实际上是您所声称的后代,通过语言外部的方式(如对象中的标志)。只要检查结果(指针)或考虑到可能的异常(引用),dynamic_cast<>()就是安全的。

另一方面,reinterpret_cast<>()(或const_cast<>())总是危险的。你告诉编译器:“相信我:我知道这看起来不像一个foo(这看起来好像它不是可变的),但它是”。

第一个问题是,如果不查看大量分散的代码段并了解所有规则,几乎不可能判断在c风格的强制转换中会出现哪一个。

让我们假设这些:

class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

现在,这两个是用同样的方式编译的:

CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
                                     // Safe; as long as we checked
                                     // but harder to read

然而,让我们看看这段几乎相同的代码:

CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert

pOther = (CMyOtherStuff*)(pSomething);            // No compiler error.
                                                  // Same as reinterpret_cast<>
                                                  // and it's wrong!!!

如您所见,如果不了解所涉及的所有类,就无法简单地区分这两种情况。

第二个问题是c风格的类型转换很难定位。在复杂表达式中,很难看到c风格的强制转换。如果没有完整的c++编译器前端,几乎不可能编写一个需要定位C风格强制转换的自动化工具(例如搜索工具)。另一方面,很容易搜索“static_cast<”或“reinterpret_cast<”。

pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
      // No compiler error.
      // but the presence of a reinterpret_cast<> is 
      // like a Siren with Red Flashing Lights in your code.
      // The mere typing of it should cause you to feel VERY uncomfortable.

这意味着,不仅c风格的类型转换更危险,而且很难找到它们以确保它们是正确的。

其他回答

一个实用的提示:如果您计划整理项目,可以在源代码中轻松搜索static_cast关键字。

In short: static_cast<>() gives you a compile time checking ability, C-Style cast doesn't. static_cast<>() can be spotted easily anywhere inside a C++ source code; in contrast, C_Style cast is harder to spot. Intentions are conveyed much better using C++ casts. More Explanation: The static cast performs conversions between compatible types. It is similar to the C-style cast, but is more restrictive. For example, the C-style cast would allow an integer pointer to point to a char. char c = 10; // 1 byte int *p = (int*)&c; // 4 bytes Since this results in a 4-byte pointer pointing to 1 byte of allocated memory, writing to this pointer will either cause a run-time error or will overwrite some adjacent memory. *p = 5; // run-time error: stack corruption In contrast to the C-style cast, the static cast will allow the compiler to check that the pointer and pointee data types are compatible, which allows the programmer to catch this incorrect pointer assignment during compilation. int *q = static_cast<int*>(&c); // compile-time error

阅读更多: static_cast<>和C风格强制转换有什么区别 而且 常规强制转换与静态强制转换与动态强制转换

Static_cast除了操作指向类的指针外,还可以用于执行类中显式定义的转换,以及执行基本类型之间的标准转换:

double d = 3.14159265;
int    i = static_cast<int>(d);

主要原因是经典的C强制转换不区分static_cast<>()、reinterpret_cast<>()、const_cast<>()和dynamic_cast<>()。这四件事是完全不同的。

static_cast<>()通常是安全的。语言中存在有效的转换,或者有适当的构造函数使转换成为可能。唯一有点风险的时候是当你向下转换到一个继承类的时候;您必须确保对象实际上是您所声称的后代,通过语言外部的方式(如对象中的标志)。只要检查结果(指针)或考虑到可能的异常(引用),dynamic_cast<>()就是安全的。

另一方面,reinterpret_cast<>()(或const_cast<>())总是危险的。你告诉编译器:“相信我:我知道这看起来不像一个foo(这看起来好像它不是可变的),但它是”。

第一个问题是,如果不查看大量分散的代码段并了解所有规则,几乎不可能判断在c风格的强制转换中会出现哪一个。

让我们假设这些:

class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;

CMyBase  *pSomething; // filled somewhere

现在,这两个是用同样的方式编译的:

CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked

pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
                                     // Safe; as long as we checked
                                     // but harder to read

然而,让我们看看这段几乎相同的代码:

CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert

pOther = (CMyOtherStuff*)(pSomething);            // No compiler error.
                                                  // Same as reinterpret_cast<>
                                                  // and it's wrong!!!

如您所见,如果不了解所涉及的所有类,就无法简单地区分这两种情况。

第二个问题是c风格的类型转换很难定位。在复杂表达式中,很难看到c风格的强制转换。如果没有完整的c++编译器前端,几乎不可能编写一个需要定位C风格强制转换的自动化工具(例如搜索工具)。另一方面,很容易搜索“static_cast<”或“reinterpret_cast<”。

pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
      // No compiler error.
      // but the presence of a reinterpret_cast<> is 
      // like a Siren with Red Flashing Lights in your code.
      // The mere typing of it should cause you to feel VERY uncomfortable.

这意味着,不仅c风格的类型转换更危险,而且很难找到它们以确保它们是正确的。

Static_cast意味着您不能意外地使用const_cast或reinterpret_cast,这是一件好事。