您的位置:首页 > 其它

强转 static_cast dynamic_cast reinterpret_cast 疑难杂症

2016-07-27 18:28 316 查看
总结了一些疑问,<span style="color:#ff0000;">如果有什么错误,还望大家指正~</span>
1.static_cast和强转有什么区别?
(1)相同:首先都是在编译时完成
(2)区别:前者更安全,如:
class A{}
class B{}
[1]A* pA = (A*)new B;-----编译通过
[2]A* pA = static_cast<A*>(new B)编译失败

2.为什么不是所有static_cast都可以用dynamic_cast代替?
(1)效率问题
(2)某些情况编译问题,如:
class A{}
class B : public A{}
A* pA = new B;
[1]B* pB = static_cast<B*>(pA);-----编译通过
[2]B* pB = dynamic_cast<B*>(pA);-----编译失败
其实这里是因为dynamic_cast更牛逼导致的,至于原因,我们看问题3.

3.为什么问题2.的dynamic_cast编译不过?
(1)编译报错:dynamic_cast的操作数必须包含多态类类型
(2)这是因为编译器实现虚函数考的是虚函数表(Vtable),如果没有虚函数存在,编译器没有必要浪费空间
实现一个虚指针
(3)所以这里如果想让编译通过,在A中添加一个虚函数ok了,如:
class A { virtual void f() }
注:这里补充一下虚表和虚指针的知识:
[1]虚表:存在虚函数的类都有一个一维的虚函数表
[2]虚指针:类的对象有一个指向虚表开始的虚指针
[3]虚表和类对应,虚指针和对象对应

4.什么情况只能用dynamic_cast而不能用static_cast?
(1)看代码:把A转成兄弟B,就不能用static_cast
class A { virtual void f(){} }
class B {}
class C : public A, public B
A* pA = new C;
[1]B* pB = static_cast<B*>(pA);-----编译失败:类型转换无效
[2]B* pB = dynamic_cast<B*>(pA);-----编译通过

5.reinterpret_cast
(1)字面意思:interpret:解释、诠释;reinterpret:重新解释
(2)reinterpret_cast<type-id> (expression):
[1]百度百科:type-id必须是一个指针、引用、算数类型、函数指针或者成员指针。它可以把一个指针转换成一个
整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该证书转换成原类型的指针
,还可以得到原先的指针值)
[2]为什么type-id要做如此限制?看代码:
char* str = "aTTTbT";
int* pA = reinterpret_cast<int*>(str);
printf("%d\n", *(++pA)); // 21602 = "bT"的二进制转成int = 'T' * 256 + 'b';
printf("%d-%d\n", pA, str); // "19257864-19257864" : 同一内存块
这说明reinterpret_cast的作用只是把同一块内存代码诠释成不同的类型罢了,挺危险的。。。
[3]然后再来看看与static_cast的区别
class A {int m_a; int m_aa;}
class B {int m_b;}
class C : public A, public B {}
C c;
printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));
// 结果 = “004FFB68, 004FFB68, 004FFB70”
这是因为static_cast计算父子类指针的偏移量,并将之转换到正确地址(偏移了两个int:m_a, m_aa),
而reinterpret_cast并没有这样做,而是保持内容不变
[4]什么时候用到reinterpret_cast?
我只知道一种,还是百度出来的:
“最普通的用途就是在函数指针类型之间进行转换”
int doSomething(){return 0;};
typedef void(*FuncPtr)();
FuncPtr funcPtrArray[10];
[4-1]funcPtrArray[0] = &doSomething;-----编译失败:返回值类型不匹配
[4-2]funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething);-----编译通过
<span style="background-color: rgb(255, 204, 204);"><span style="color:#ff0000;">如果大家还知道有什么用处,请多多指教~</span></span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: