解决方法
主要原因是经典的C转换不会区分我们所说的static_cast(),reinterpret_cast(),const_cast()和dynamic_cast()之间的区别.这四件事是完全不一样的.
static_cast<>()通常是安全的.语言中有一个有效的转换,或一个适当的构造函数,使它成为可能.唯一有时候冒险的就是当你被遗弃的时候,您必须确保该对象实际上是您声称的后代,通过外部的语言(如对象中的标志).只要结果被检查(指针)或可能的异常被考虑(参考),dynamic_cast()就是安全的.
另一方面,reinterpret_cast<>()(或const_cast())总是危险的.你告诉编译器:“相信我:我知道这不像一个foo(看起来好像不可变),但它是”.
第一个问题是,几乎不可能知道哪一个将发生在C风格的演员中,而不必考虑大型和分散的代码段,并且知道所有的规则.
我们假设这些:
class CMyClass : public CMyBase {...}; class CMyOtherStuff {...} ; CMyBase *pSomething; // filled somewhere
现在,这两个编译方式相同:
CMyClass *pMyObject; pMyObject = static_cast<CMyClass*>(pSomething); // Safe; as long as we checked pMyObject = (CMyClass*)(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风格的风格更加危险,而且要找到所有这些都是非常困难的,以确保它们是正确的.