强转 static_cast dynamic_cast reinterpret_cast 疑难杂症

	
总结了一些疑问,<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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值