https://stackoverflow.com/questions/103512/why-use-static-castintx-instead-of-intx
https://stackoverflow.com/questions/2253168/dynamic-cast-and-static-cast-in-c
C 风格的强制类型转换形如 (type)(var)
,而 C++ 提出了四种不同的用于强制类型转换的操作符,static_cast<type>(var)
、const_cast<type>(var)
、dynamic_cast<type>(var)
和 reinterpret_cast<type>(var)
。
那 C++ 为什么要新引入这四种类型转换的操作符呢?原因在于 C 风格的类型转换适用范围太广,其中有些转换是相对安全的,例如 char
转换成 int
,但也有一些类型转换是相对危险的,例如将指向基类的指针转换成派生类的指针。所以 C++ 要求程序员根据不同的情况选用不同的类型转换方式,从而增强类型的安全性。
static_cast<type>(var)
相对安全的类型转换都可以通过 static_cast
完成,这里的相对安全是和其他三种类型类型转换相对而言的。一些基本的类型转换例如 int
转换成 char
都可以使用 static_cast
完成。
static_cast
唯一允许的一种比较危险的类型转换是将基类指针转换成派生类指针,不管这个指针到底指向的是一个派生类对象还是基类对象。另一种类型转换方式 dynamic_cast
为这种类型转换提供了更高的安全性。
dynamic_cast<type>(var)
如上所述,dynamic_cast
可以为类指针之间的强制转换提供更高的安全性。
对于指向派生类的指针转换成指向基类指针这种情况,可以知道这种转换一定是安全的,所以用 static_cast
或者 dynamic_cast
都无所谓。而将指向基类的指针转换成派生类指针这种情况就可能会有安全性的问题。看下面的例子:
class Base
{
public:
virtual void func() {}
};
class DerivedA : public Base
{
public:
virtual void func() {}
};
class DerivedB : public Base
{
public:
virtual void func() {}
};
int main()
{
Base* ptrA = new DerivedA;
DerivedA* realA = dynamic_cast<DerivedA *>(ptrA);
DerivedB* realB = dynamic_cast<DerivedB *>(ptrA);
cout << realA << endl; // 0x55a4175e0eb0
cout << realB << endl; // 0
return 0;
}
可以看到,将指向 DerivedA
的基类指针用 dynamic_cast
转换成 DerivedA
指针可以成功转换,最后正确的输出了指针的值。而将指向 DerivedA
的基类指针用 dynamic_cast
转换成 DerivedB
指针后,这个指针的值是 0。也就是 dynamic_cast
在进行这种转换的时候会检查这个指针真正指向的类型与要转换成的类型是否相同,如果相同则可以成功转换,否则返回 0。还有要注意的一点是如果想让 dynamic_cast
正确处理这种情况,则这些要转换的类必须具有多态性,说白了就是至少要有一个虚函数。
这也是 dynamic_cast
更安全的原因,如果使用 static_cast
则上面的 realA
和 realB
都将是正确的地址,此时使用 realB
访问一些 DerivedB
独有的内容就会出错。
const_cast<type>(var)
const_cast
用于去除变量的底层const属性。所谓底层const属性表示这个变量所指向的内容是不可变的,而相对的顶层const则表示这个变量自身是不可变的。例如 const int* ptr
是底层const,int* const ptr
是顶层const。
如上所说,const_cast
可以去除变量的底层const属性。
int i = 1;
const int* ptr = &i;
int* ptr1 = const_cast<int *>(ptr);
(*ptr1)++; // correct
在这个例子中,ptr
指向的变量 i
是可变的,所以可以通过 const_cast
将 ptr
的 const
去掉从而修改 i
的值,这样写是合法。但假如 i
本身就是一个 const
变量,则上面的这种用法在语法上还是合法的,只不过最终 i
的值变不变是未定义的。
reinterpret_cast<type>(var)
reinterpret_cast
是最神奇的一种类型转换方式。C++ Primer 对其的解释为:reinterpret_cast
操作符通常为操作数的位模式提供较低层次的重新解释。
typedef void(*pfun)();
int func(int i) {
cout << "Print: " << i << endl;
return i;
}
int main() {
pfun ptr = reinterpret_cast<pfun>(func);
ptr();
return 0;
}
可以看到,一个 int(*)(int)
的函数指针类型被转换成了 void(*)()
类型,还调用成功了!所以 reinterpret_cast
非常变态,C++ Primer 说到,reinterpret_cast
本质上依赖于机器,想要安全的使用 reinterpret_cast
必须对涉及的类型和编译器实现转换的过程都非常了解。
4 条评论
咋不更新了老哥
老哥,你怎么不更新了呢
看到你的网站,觉得很不错,希望能与你互相友情链接…
我的网站:建站知道网-http://wozhidaole.com.cn/
如果同意的话,回复后互相上链接!
C++ 强制类型性转换将的很详细,感谢博主分享