C++ 为什么使用静态_cast<;int>;(x) 而不是(int)x?
我听说比起C风格或简单功能风格的转换,C++ 为什么使用静态_cast<;int>;(x) 而不是(int)x?,c++,casting,static-cast,C++,Casting,Static Cast,我听说比起C风格或简单功能风格的转换,static\u cast功能应该更受欢迎。这是真的吗?为什么?static\u cast除了操作指向类的指针外,还可用于执行类中显式定义的转换,以及执行基本类型之间的标准转换: double d = 3.14159265; int i = static_cast<int>(d); double d=3.14159265; int i=静态(d); static\u cast意味着您不能意外地const\u cast或重新解释\u cas
static\u cast
功能应该更受欢迎。这是真的吗?为什么?static\u cast除了操作指向类的指针外,还可用于执行类中显式定义的转换,以及执行基本类型之间的标准转换:
double d = 3.14159265;
int i = static_cast<int>(d);
double d=3.14159265;
int i=静态(d);
static\u cast
意味着您不能意外地const\u cast
或重新解释\u cast
,这是一件好事。这是关于您想要施加多少类型安全性的问题
当您编写(bar)foo
(如果您没有提供类型转换运算符,这相当于重新解释\u cast foo
)时,您告诉编译器忽略类型安全性,只需按照要求执行即可
当您编写static\u cast foo
时,您要求编译器至少检查类型转换是否有意义,并且对于整型类型,插入一些转换代码
编辑2014-02-26
我在5年多前写下了这个答案,但我弄错了。(见评论)但它仍然获得了更多的选票 一个实用技巧:如果你打算整理项目,你可以在源代码中轻松搜索static\u cast关键字。主要原因是经典的C cast没有区分我们所称的
static\u cast()
,reinterpret\u cast()
,const\u cast()
,和dynamic\u cast()
。这四件事是完全不同的
static\u cast()
通常是安全的。语言中有一个有效的转换,或者有一个合适的构造函数使之成为可能。唯一有点冒险的时候是当你放弃继承类时;您必须确保该对象实际上是您声称的后代,方法是语言外部的(如对象中的标志)。只要检查结果(指针)或考虑到可能的异常(参考),则动态\u 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
CDerivedClass*pMyObject;
pMyObject=静态_转换(pSomething);//安全的;只要我们检查过
pMyObject=(CDerivedClass*)(pSomething);//与静态_cast相同
//安全的;只要我们检查过
//但更难阅读
但是,让我们看一下几乎相同的代码:
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!!!
CMyOtherStuff*pOther;
pOther=静态施法(pSomething);//编译器错误:无法转换
pOther=(CMyOtherStuff*)(pSomething);//没有编译器错误。
//与重新解释_cast相同
//这是错误的!!!
正如您所看到的,如果不了解所有涉及的类,就很难区分这两种情况
第二个问题是C样式转换太难定位。在复杂表达式中,很难看到C样式转换。几乎不可能编写一个自动化工具,它需要定位C风格的铸件(例如搜索工具),而不需要完全的C++编译器前端。另一方面,很容易搜索“StasyStudio
”,问题不仅仅是使用枯萎的STATICE-CAST或C型的铸造,因为在使用C样式的铸件时会发生不同的事情。C++的铸造操作符旨在使这些操作更加明确。 在曲面上,静态类型转换和C样式转换显示为相同的内容,例如,将一个值转换为另一个值时:
int i;
double d = (double)i; //C-style cast
double d2 = static_cast<double>( i ); //C++ cast
inti;
双d=(双)i;//C样式转换
double d2=static_cast(i);//C++cast
这两种方法都将整数值转换为双精度。但是,当使用指针时,事情会变得更复杂。一些示例:
class A {};
class B : public A {};
A* a = new B;
B* b = (B*)a; //(1) what is this supposed to do?
char* c = (char*)new int( 5 ); //(2) that weird?
char* c1 = static_cast<char*>( new int( 5 ) ); //(3) compile time error
A类{};
B类:公共A{};
A*A=新的B;
B*B=(B*)a;//(1)这应该做什么?
char*c=(char*)新的int(5);/(2)那奇怪吗?
char*c1=static_cast(新int(5));/(3)编译时错误
在这个例子中(1)可能是可以的,因为A指向的对象实际上是B的实例。但是如果你在代码中不知道A实际指向的是什么呢?(2)可能是完全合法的(你只想看整数的一个字节),但也可能是个错误,在这种情况下,错误会很好,如(3)C++的C铸造运算符旨在通过提供编译时间或运行时错误,在代码中暴露这些问题。
因此,对于严格的“值转换”,您可以使用静态转换。如果您想要运行时多态性转换指针,请使用动态转换。如果您真的想忘记类型,可以使用ReintRecpret转换。要将const抛出窗口,有const转换
<>他们只是让代码更显,这样看起来你知道你在做什么。< P> C风格的转换在一个代码块中很容易被忽略。C++风格的转换不仅仅是更好的实践;它们提供了更大的灵活性。 reinterpret_cast允许整数到指针类型的转换,但如果使用不当,则可能不安全 static_cast为数字类型提供了良好的转换,例如从as enum到int或int到float或任何您确信类型的数据类型。它不执行任何运行时检查<
class A {};
class B : public A {};
A* a = new B;
B* b = (B*)a; //(1) what is this supposed to do?
char* c = (char*)new int( 5 ); //(2) that weird?
char* c1 = static_cast<char*>( new int( 5 ) ); //(3) compile time error
char c = 10; // 1 byte
int *p = (int*)&c; // 4 bytes
*p = 5; // run-time error: stack corruption
int *q = static_cast<int*>(&c); // compile-time error