关于C++强制类型转换操作结果的总结

上一篇 / 下一篇  2012-10-15 13:21:29 / 个人分类:C++

51Testing软件测试网df%@|4D*I~I0p7\

  C++类型转换在刚学习C++不久就接触到的东西,由于那会儿对C++机制的不熟悉,并没有太多的疑问。随着对C++进一步的了解,基本类型转 换应该可以理解为生成了对应类型的临时变量。昨天看到了Effective C++条款3中,类的const与non-const重载函数,non-const函数调用const函数实现重载,即所谓的常量性转除(casting away constness)。示例程序代码如下:

UL!B4nSE0
class CTextBox51Testing软件测试网N9`W S~
{51Testing软件测试网0vL3^YwO ??/i
public:51Testing软件测试网u WRh$u;g^z
CTextBox(void);51Testing软件测试网 XV4S`fb
CTextBox(char *szStr);
.S!kF+s dIu)o0~CTextBox(void);
FvgM r'ru0const char& operator[](std::size_t pos) const
u8Ty/U%qx0{ return m_strText[pos]; }
:m v%E ~%`r\a0char& operator[](std::size_t pos)
?/M|b4Ik.[0{51Testing软件测试网tQRx:M%}vN
return const_cast<char&>((static_cast<const CTextBox&>(*this))[pos]);
{0M ss*L(A^"L1Q"jb${0}
ovH.rYCQ0private:
n8\6K*J0Y%Ot9Z0std::string m_strText;
J#ME\Cc s2k0};
51Testing软件测试网ZD'\$J2m4~ nx.j4~

   操作符重载函数operator[]的non-const版本对this*做了类型转换,使其能够调用const版本的operator[]函数,如果 按照基本类型转换的临时变量理解,函数最后相当于返回了对临时变量的引用,这显然是错误的,而且不能达到程序员想要的目的。但是经过对代码的编译运行,发 现程序能够通过正确运行。所以产生了如下疑问:类型转换用于常量性移除时,是否针对原变量操作,而不是生成了变量;由此考虑类型转换的其他用途,比如对于 指针的转换等,是以何种方式进行的。下面引用神秘果的blog中关于C++类型转换的总结:

W \(\&w l];y"c J051Testing软件测试网cwqv]4Qan1E

  C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:51Testing软件测试网Mh2x!}.h)h"X;oa

51Testing软件测试网NhVI@L`lt

  TYPE b = (TYPE)a。

6dR/t]K051Testing软件测试网v})?j_9mN9B

   C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。看似问题复杂化了,其实不然。C风格的类型转换在程序语句中难以识别,类型转换是 去const,还是int转换成char,或是子类指针转换成父类指针?C括号风格的强制类型转换解决不了这些问题。C++的4种类型转换能够解决这些问 题:51Testing软件测试网 aZJ G4S o"s;Z~0Ub

51Testing软件测试网/XW Z(kduq)G`

  const_cast,字面上理解就是去const属性。51Testing软件测试网*L;CfLr Y

1vWl Em%g0  static_cast,命名上理解是静态类型转换。如int转换成char。51Testing软件测试网#i{3S$x*g!Q#B

51Testing软件测试网/fHP6G-~,T.C ]3CB gR

  dynamic_cast,命名上理解是动态类型转换。如子类和父类之间的多台类型转换。51Testing软件测试网*L6h9`;M3Tz,I:at

6c:X&~.lv,E2bQ0  reinterpreter_cast,仅仅重新解释类型,但没有进行二进制的转换。51Testing软件测试网K G4l%fV

F I+fo[[0  4种类型转换的格式,如:TYPE B = static_cast(TYPE)(a)。51Testing软件测试网i9M4o l(_W:[+bw

.X$@ cXp%_,r7d0  const_cast51Testing软件测试网 C2w}8zdo'}J

!G"Yw\O6Yw0  去掉类型的const或volatile属性。

*^ P2ldf#w0struct SA {51Testing软件测试网u.L5cl;q#qv-K/]E} B
 int i;51Testing软件测试网)I mac y#r)~ m
 };51Testing软件测试网,EnVD-n
  const SA ra;
[8C4@Q*A4b9~0  //ra.i = 10; //直接修改const类型,编译错误51Testing软件测试网k6Bh7b Y5~:ch5`
  SA &rb = const_cast<SA&>(ra);51Testing软件测试网!^'n!Z8i K6E|
 rb.i = 10;51Testing软件测试网2d$Y'A)TEI7O
51Testing软件测试网%~m8@!M6CT_d2Ozc

  static_cast

i-r4C2[X7h@#U;c9v1E8e0

7u7R&VZQ#X0  类似于C风格的强制转换。无条件转换,静态类型转换。用于:51Testing软件测试网n9j)o$t7ousD)O

:D~nI4|cd0  1、基类和子类之间转换:其中子类指针转换成父类指针是安全的;但父类指针转换成子类指针是不安全的。(基类和子类之间的动态类型转换建议用dynamic_cast)51Testing软件测试网1|)Xug)V xr/E)b}Y

qs So+EO0  2、基本数据类型转换。enum,struct,int,char,float等。static_cast不能进行无关类型(如非基类和子类)指针之间的转换。

!m|3vT)c s)H8gt051Testing软件测试网*u#\w s `{oS6Pl~W

  3、把空指针转换成目标类型的空指针。51Testing软件测试网 w6rW4cEP8m5~K%oLl

51Testing软件测试网XN^l H5h-{;N5t

  4、把任何类型的表达式转换成void类型。

1R-u#Cj[#wL%{+|\)g0

"v h4z0@+|jS qF0  5、static_cast不能去掉类型的const、volitale属性(用const_cast)。51Testing软件测试网x7`;p%MyEp'?'^r

?(S Y!ee#nTa0j051Testing软件测试网"Mb4JJ8O2L/o2IS

1intn=6;
*U!ye RQ0
2 doubled=static_cast<double>(n);//基本类型转换51Testing软件测试网u5U7m {Ln
3 int*pn=&n;51Testing软件测试网.UV%s"H5dl9o
4double*d=static_cast<double*>(&n)//无关类型指针转换,编译错误
a8`*kk0bv,x;u6O0
5void*p=static_cast<void*>(pn);//任意类型转换成void类型
:u`'a)j)g]|c%?Co0
6

V"GK*v Wc0  dynamic_cast

Kt1hX0qfZMK h[051Testing软件测试网E.hp e6P7zh.q

  有条件转换,动态类型转换,运行时类型安全检查(转换失败返回NULL):51Testing软件测试网)\[ n,p4Wu%k%T

51Testing软件测试网r7E @J%@'z4L{;x{[

  1、安全的基类和子类之间转换。51Testing软件测试网0r3b$Hi,I8w

51Testing软件测试网$yV"e'i.lE f6t#\

  2、必须要有虚函数。

X"U3n8^)TB8E&|051Testing软件测试网cqKlf5iV3~V

  3、相同基类不同子类之间的交叉转换。但结果是NULL。

8s*svm0B"KMI051Testing软件测试网}5dx-WS G U

'@h,@Qw#z!~0
class BaseClass {51Testing软件测试网(I7h;[B0txC
 public:
%h4]G_;_8q;R0 int m_iNum;51Testing软件测试网NlwRg+`
 virtual void foo(){}; //基类必须有虚函数。保持多台特性才能使用dynamic_cast51Testing软件测试网0@jo&a/| n~0[7H#WO
 };
Q,a'd,c.M(~0 
k d%t/? z:s0 class DerivedClass: public BaseClass {
S3A/}C[!p-oS#W0 public:51Testing软件测试网8aYu X UEn2?
 char *m_szName[100];
~HWz5k_ V-Q s0 void bar(){};
W1_*sMbR;p;@q0 };51Testing软件测试网+OM a[X ?]v7M"[
 51Testing软件测试网g R8Qg5A"A$}7y Bn xg
 BaseClass* pb = new DerivedClass();
0B{Ogx%k-z0 DerivedClass *pd1 = static_cast<DerivedClass *>(pb); //子类->父类,静态类型转换,正确但不推荐
4Y-ir o J0 DerivedClass *pd2 = dynamic_cast<DerivedClass *>(pb); //子类->父类,动态类型转换,正确51Testing软件测试网p i^;b"M A/_([m)W
 
U5~#g s{[p0 BaseClass* pb2 = new BaseClass();51Testing软件测试网h:kgZ/cc-q
 DerivedClass *pd21 = static_cast<DerivedClass *>(pb2); //父类->子类,静态类型转换,危险!访问子类m_szName成员越界51Testing软件测试网 Ev;Z"o1s.vY
 DerivedClass *pd22 = dynamic_cast<DerivedClass *>(pb2); //父类->子类,动态类型转换,安全的。结果是NULL

q9e]F*{6r0k0  reinterpret_cast

s-yz0t+a?Ux.~6J051Testing软件测试网+Cg&|6W-X9m @#C6n

  仅仅重新解释类型,但没有进行二进制的转换:51Testing软件测试网.PzBsHh

51Testing软件测试网)jt6sFl?0_

  1、转换的类型必须是一个指针、引用、算术类型、函数指针或者成员指针。51Testing软件测试网&pys2[0a_4P

&Y-GK3?q'xIf)emA0  2、在比特位级别上进行转换。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。但不能将非32bit的实例转成指针。

+t%dL![4Kyj.hq;q3v6x051Testing软件测试网7k?2N Vy

  3、最普通的用途就是在函数指针类型之间进行转换。51Testing软件测试网v2n6X,gy m{ `r

51Testing软件测试网Ef&b ?W%v2g/a

  4、很难保证移植性。

KP!d1T6M3Y(`o051Testing软件测试网A X3Fn:z b_)b%y

51Testing软件测试网x%~0c'F"U'w6rW6ey

int doSomething(){return 0;};51Testing软件测试网5L0Y _Ic;UeI&h4J^
 typedef void(*FuncPtr)(); //FuncPtr is 一个指向函数的指针,该函数没有参数,返回值类型为 void
j A\ x0@0 FuncPtr funcPtrArray[10]; //10个FuncPtrs指针的数组 让我们假设你希望(因为某些莫名其妙的原因)把一个指向下面函数的指针存入funcPtrArray数组:
%k9A-{-S-Sc2QN0 51Testing软件测试网*l&Rwm9kAU3@
 funcPtrArray[0] = &doSomething;// 编译错误!类型不匹配,reinterpret_cast可以让编译器以你的方法去看待它们:funcPtrArray
(Sjm9K;`0 funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething); //不同函数指针类型之间进行转换

,]7v^8K Ol9g1AZM0  总结51Testing软件测试网7cnO7JEz

51Testing软件测试网W _VhR

  去const属性用const_cast。

)~Z7r7J'A w.j$cV(}0

T.l.{*I1u6O7c G0  基本类型转换用static_cast。51Testing软件测试网J Y*DL%h K'\ ir

DU'M#ANM UGc9r6c0  多台类之间的类型转换用daynamic_cast。

6s,nm`9A3t$M0

.PA(U'A ^B+HnbU a0  不同类型的指针类型转换用reinterpret_cast。51Testing软件测试网Z5hv!k;mq&O*O a

51Testing软件测试网n-gl0\|2rn

  关于强制类型转的操作结果问题,可以简单总结为non-pointer变量,即基本类型和类类型产生临时变量。而指针变量只是编译器对其的解释 方式不同而已,因此类型转换也是对其本身操作的,也就是改变了解释方式。另外变量的去const与加const转换也是在变量上直接操作,因为const 是欺骗编译器的一个标志。51Testing软件测试网?,k.k sY


\ | E(Xn/i0

TAG:

 

评分:0

我来说两句

Open Toolbar