Whentousewhichcastinc:Usedynamiccastforconvertingpointersreferenceswithinaninheritancehierarchy。 Usestaticcastforordinarytypeconversions。 Usereinterpretcastforlowlevelreinterpretingofbitpatterns。Usewithextremecaution。 Useconstcastforcastingawayconstvolatile。AvoidthisunlessyouarestuckusingaconstincorrectAPI。 Calsosupportsfunctionstylecastnotation,T(expr),andCstylecastnotation,(T)expr。 C还支持函数样式转换表示法T(expr)和C风格类型转换表示法(T)expr。 CStylecastingcanbeconsideredBesteffortcastingandisnamedsoasitistheonlycastwhichcouldbeusedinC。Thesyntaxforthiscastis(NewType)variable。 C风格类型转换表示法可以被认为是尽力而为的casting,之所以这样命名,是因为它是唯一可以在C中使用的cast。该cast的语法是(NewType)变量。 Wheneverthiscastisused,itusesoneofthefollowingccasts(inorder): 每当使用此强制转换时,它都会使用以下c强制转换之一(按顺序):constcastNewType(variable)staticcastNewType(variable)constcastNewType(staticcastconstNewType(variable))reinterpretcastconstNewType(variable)constcastNewType(reinterpretcastconstNewType(variable)) Functionalcastingisverysimilar,thoughasafewrestrictionsastheresultofitssyntax:NewType(expression)。Asaresult,onlytypeswithoutspacescanbecastto。 函数式强制转换非常相似,但由于其语法的原因有一些限制:NewType(表达式)。因此,只有不带空格的类型才能被强制转换。 Itsbettertousenewccast,becausesmorereadableandcanbespottedeasilyanywhereinsideaCsourcecodeanderrorswillbedetectedincompiletime,insteadinruntime。 最好使用新的ccast,因为它更具可读性,并且可以在c源代码中的任何位置轻松发现,错误将在编译时而不是在运行时被检测到。 Asthiscastcanresultinunintendedreinterpretcast,itisoftenconsidereddangerous。 由于该类型转换可能会导致意外的重新诠释,因此通常被认为是危险的。1Castingawayconstness Apointertoaconstobjectcanbeconvertedtoapointertononconstobjectusingtheconstcastkeyword。Hereweuseconstcasttocallafunctionthatisnotconstcorrect。Itonlyacceptsanonconstcharargumenteventhoughitneverwritesthroughthepointer: 指向常量对象的指针可以使用constcast关键字转换为指向非常量对象的指针。这里我们使用constcast来调用一个非constcorrect的函数。它只接受非常量char参数,即使它从未通过指针写入:voidbadstrlen(char);constcharshello,world!;badstrlen(s);compileerrorbadstrlen(constcastchar(s));OK,butitsbettertomakebadstrlenacceptconstchar constcasttoreferencetypecanbeusedtoconvertaconstqualifiedlvalueintoanonconstqualifiedvalue。 constcast引用类型可用于将常量限定左值转换为非常量限定值。 constcastisdangerousbecauseitmakesitimpossiblefortheCtypesystemtopreventyoufromtryingtomodifyaconstobject。Doingsoresultsinundefinedbehavior。 constcast是危险的,因为它使C类型系统无法阻止您尝试修改const对象。这样做会导致未定义的行为。constintx123;intmutablexconstcastint(x);mutablex456;maycompile,butproducesundefinedbehavior2Basetoderivedconversion Apointertobaseclasscanbeconvertedtoapointertoderivedclassusingstaticcast。staticcastdoesnotdoanyruntimecheckingandcanleadtoundefinedbehaviourwhenthepointerdoesnotactuallypointtothedesiredtype。 可以使用staticcast将指向基类的指针转换为指向派生类的指针。staticcast不执行任何运行时检查,当指针实际上没有指向所需类型时,可能会导致未定义的行为。structBase{};structDerived:Base{};DBasep1d;Derivedp2p1;castrequiredDerivedp3staticcastDerived(p1);OK;p2nowpointstoDerivedobjectBBasep4b;Derivedp5staticcastDerived(p4);undefinedbehavioursincep4doesnotpointtoaDerivedobject Likewise,areferencetobaseclasscanbeconvertedtoareferencetoderivedclassusingstaticcast。 同样,对基类的引用可以使用staticcast转换为对派生类的引用。structBase{};structDerived:Base{};DBaser1d;Derivedr2r1;castrequiredDerivedr3staticcastDerived(r1);OK;r3nowreferstoDerivedobject Ifthesourcetypeispolymorphic,dynamiccastcanbeusedtoperformabasetoderivedconversion。Itperformsaruntimecheckandfailureisrecoverableinsteadofproducingundefinedbehaviour。Inthepointercase,anullpointerisreturneduponfailure。Inthereferencecase,anexceptionisthrownuponfailureoftypestd::badcast(oraclassderivedfromstd::badcast)。 如果源类型是多态的,则可以使用dynamiccast执行从基类到派生类的转换。它执行运行时检查,错误是可恢复的,而不是产生未定义的行为。在指针情况下,失败时返回空指针。在引用情形下,std::badcast类型(或从std::badcast派生的类)失败时会引发异常。structBase{virtualBase();};BaseispolymorphicstructDerived:Base{};Baseb1newDDerivedd1dynamiccastDerived(b1);OK;d1pointstoDerivedobjectBaseb2newBDerivedd2dynamiccastDerived(b2);d2isanullpointer3Conversionbetweenpointerandinteger Anobjectpointer(includingvoid)orfunctionpointercanbeconvertedtoanintegertypeusingreinterpretcast。Thiswillonlycompileifthedestinationtypeislongenough。Theresultisimplementationdefinedandtypicallyyieldsthenumericaddressofthebyteinmemorythatthepointerpointersto。 可以使用reinterpretcast将对象指针(包括void)或函数指针转换为整数类型。只有在目标类型足够长的情况下,才会编译。结果是实现定义的,通常会生成指针指向的内存字节的数字地址。 Typically,longorunsignedlongislongenoughtoholdanypointervalue,butthisisnotguaranteedbythestandard。 通常,long或unsignedlong的长度足以容纳任何指针值,但该标准不保证这一点。 Ifthetypesstd::intptrtandstd::uintptrtexist,theyareguaranteedtobelongenoughtoholdavoid(andhenceanypointertoobjecttype)。However,theyarenotguaranteedtobelongenoughtoholdafunctionpointer。 如果std::intptrt和std::uintptrt类型存在,则保证它们的长度足以容纳一个void(以及任何指向对象类型的指针)。然而,它们不能保证足够长的时间来容纳函数指针。 Similarly,reinterpretcastcanbeusedtoconvertanintegertypeintoapointertype。Againtheresultisimplementationdefined,butapointervalueisguaranteedtobeunchangedbyaroundtripthroughanintegertype。Thestandarddoesnotguaranteethatthevaluezeroisconvertedtoanullpointer。 类似地,reinterpretcast可用于将整数类型转换为指针类型。同样,结果是实现定义的,但通过整数类型的往返,指针值保证不变。该标准不保证将零值转换为空指针。voidregistercallback(void(fp)(void),voidarg);probablyaCAPIvoidmycallback(voidx){std::coutthevalueis:reinterpretcastlong(x);willprobablycompile}std::registercallback(mycallback,reinterpretcastvoid(x));hopefullythisdoesntloseinformation。。。4Conversionbyexplicitconstructororexplicit Aconversionthatinvolvescallinganexplicitconstructororconversionfunctioncantbedoneimplicitly。Wecanrequestthattheconversionbedoneexplicitlyusingstaticcast。Themeaningisthesameasthatofadirectinitialization,exceptthattheresultisatemporary。 涉及调用显式构造函数或转换函数的转换不能隐式完成。我们可以请求使用staticcast显式地完成转换。其含义与直接初始化相同,只是结果是临时的。classC{std::public:explicitC(intp):p(p){}};voidf(Cc);voidg(intp){f(p);error:C::C(int)isexplicitf(staticcastC(p));okf(C(p));equivalenttopreviouslineCc(p);f(c);error:Cisnotcopyable}5Implicitconversion staticcastcanperformanyimplicitconversion。Thisuseofstaticcastcanoccasionallybeuseful,suchasinthefollowingexamples: staticcast可以执行任何隐式转换。这种staticcast的使用有时会很有用,例如在以下示例中: Whenpassingargumentstoanellipsis,theexpectedargumenttypeisnotstaticallyknown,sonoimplicitconversionwilloccur。 将参数传递给省略号时,预期参数类型不是静态已知的,因此不会发生隐式转换。constdoublex3。14;printf(d,staticcastint(x));prints3printf(d,x);printfisexpectinganintherealternative:printf(d,y); Withouttheexplicittypeconversion,adoubleobjectwouldbepassedtotheellipsis,andundefinedbehaviourwouldoccur。 如果没有显式类型转换,一个double对象将被传递给省略号,并且会发生未定义的行为。 Aderivedclassassignmentoperatorcancallabaseclassassignmentoperatorlikeso: 派生类赋值运算符可以调用基类赋值运算符,如下所示:structBase{。。。};structDerived:Base{Derivedoperator(constDerivedother){staticcastBase(this)alternative:B}};6Enumconversions staticcastcanconvertfromanintegerorfloatingpointtypetoanenumerationtype(whetherscopedorunscoped),andviceversa。Itcanalsoconvertbetweenenumerationtypes。 staticcast可以从整数或浮点类型转换为枚举类型(无论是作用域还是非作用域),反之亦然。它还可以在枚举类型之间转换。 Titispossible,butnotnecessary,tousestaticcast。 从无范围枚举类型到算术类型的转换是隐式转换;可以使用staticcast,但不是必须的。 Whenascopedenumerationtypeisconvertedtoanarithmetictype: 当作用域枚举类型转换为算术类型时: Iftheenumsvaluecanberepresentedexactlyinthedestinationtype,theresultisthatvalue。 如果枚举的值可以在目标类型中精确表示,则结果就是该值。 Otherwise,ifthedestinationtypeisanintegertype,theresultisunspecified。 否则,如果目标类型是整数类型,则结果是未指定的。 Otherwise,ifthedestinationtypeisafloatingpointtype,theresultisthesameasthatofconvertingtotheunderlyingtypeandthentothefloatingpointtype。 否则,如果目标类型是浮点类型,则结果与转换为基础类型然后再转换为浮点类型的结果相同。enumclassFormat{TEXT0,PDF1000,OTHER2000,};FormatfFormat::PDF;errorintbstaticcastint(f);bis1000charcstaticcastchar(f);unspecified,if1000doesntfitintochardoubledstaticcastdouble(f);dis1000。0。。。probably Whenanintegerorenumerationtypeisconvertedtoanenumerationtype: 将整数或枚举类型转换为枚举类型时: Iftheoriginalvalueiswithinthedestinationenumsrange,theresultisthatvalue。Notethatthisvaluemightbeunequaltoallenumerators。 如果原始值在目标枚举的范围内,则结果为该值。请注意,此值可能不等于所有枚举数。 Otherwise,theresultisunspecified(C14)orundefined(C17)。 否则,结果为未指定(C14)或未定义(C17)。enumScale{SINGLE1,DOUBLE2,QUAD4};Scales11;errorScales2staticcastScale(2);s2isDOUBLEScales3staticcastScale(3);s3hasvalue3,andisnotequaltoanyenumeratorScales9staticcastScale(9);unspecifiedvalueinC14;UBinC17 Whenafloatingpointtypeisconvertedtoanenumerationtype,theresultisthesameasconvertingtotheenumsunderlyingtypeandthentotheenumtype。 将浮点类型转换为枚举类型时,结果与先转换为枚举的基础类型,然后再转换为枚举类型相同。enumDirection{UP0,LEFT1,DOWN2,RIGHT3,};DirectiondstaticcastDirection(3。14);disRIGHT7Derivedtobaseconversionforpointerstomembers Apointertomemberofderivedclasscanbeconvertedtoapointertomemberofbaseclassusingstaticcast。 可以使用staticcast将指向派生类成员的指针转换为指向基类成员的指针。 Thetypespointedtomustmatch。 指向的类型必须匹配。 Iftheoperandisanullpointertomembervalue,theresultisalsoanullpointertomembervalue。 如果操作数是指向成员值的空指针,则结果也是指向成员值的空指针。 Otherwise,theconversionisonlyvalidifthememberpointedtobytheoperandactuallyexistsinthedestinationclass,orifthedestinationclassisabaseorderivedclassoftheclasscontainingthememberpointedtobytheoperand。staticcastdoesnotcheckforvalidity。Iftheconversionisnotvalid,thebehaviourisundefined。 否则,只有当操作数指向的成员实际存在于目标类中,或者目标类是包含操作数指向的成员的类的基类或派生类时,转换才有效。staticcast不检查有效性。如果转换无效,则行为未定义。structA{};structB{};structC:A,B{};intB::p1B::x;intC::p2p1;implicitconversionintB::p3p2;errorintB::p4staticcastintB::(p2);p4isequaltop1intA::p5staticcastintA::(p2);p2pointstox,whichisamemberoftheunrelatedclassBdoubleC::p6C::z;doubleA::p7staticcastdoubleA::(p6);ok,eventhoughAdoesntcontainzintA::p8staticcastintA::(p6);error:typesdontmatch8voidtoT InC,voidcannotbeimplicitlyconvertedtoTwhereTisanobjecttype。Instead,staticcastshouldbeusedtoperformtheconversionexplicitly。IftheoperandactuallypointstoaTobject,theresultpointstothatobject。 在C中,void不能隐式转换为T,其中T是对象类型。相反,应该使用staticcast显式地执行转换。如果操作数实际指向一个T对象,则结果指向该对象。 Otherwise,theresultisunspecified。 否则,结果未明。 EveniftheoperanddoesnotpointtoaTobject,aslongastheoperandpointstoabytewhoseaddressisproperlyalignedforthetypeT,theresultoftheconversionpointstothesamebyte。 即使操作数不指向T对象,只要操作数指向的字节的地址与类型T正确对齐,转换结果也会指向同一字节。allocatinganarrayof100ints,thehardwayintamalloc(100sizeof(a));mallocreturnsvoidintastaticcastint(malloc(100sizeof(a)));okintanewint〔100〕;nocastneededstd::vectorinta(100);betterconstcharc!;constvoidp1c;constcharp2p1;errorconstcharp3staticcastconstchar(p1);p3pointstocconstintp4staticcastconstint(p1);unspecifiedinC03;possiblyunspecifiedinC11ifalignof(int)alignof(char)charp5staticcastchar(p1);error:castingawayconstness9Typepunningconversion Apointer(resp。reference)toanobjecttypecanbeconvertedtoapointer(resp。reference)toanyotherobjecttypeusingreinterpretcast。Thisdoesnotcallanyconstructorsorconversionfunctions。 可以使用reinterpretcast将指向对象类型的指针(响应引用)转换为指向任何其他对象类型的指针(响应引用)。这不会调用任何构造函数或转换函数。intx42;charpstaticcastchar(x);error:staticcastcannotperformthisconversioncharpreinterpretcastchar(x);OKmaybethismodifiesx(seebelow) Theresultofreinterpretcastrepresentsthesameaddressastheoperand,providedthattheaddressisappropriatelyalignedforthedestinationtype。Otherwise,theresultisunspecified。 reinterpretcast的结果表示与操作数相同的地址,前提是地址与目标类型正确对齐。否则,结果未明。intx42;charrreinterpretcastchar(x);assert(pxpr);shouldneverfire Theresultofreinterpretcastisunspecified,exceptthatapointer(resp。reference)willsurvivearoundtripfromthesourcetypetothedestinationtypeandback,aslongasthedestinationtypesalignmentrequirementisnotstricterthanthatofthesourcetype。 reinterpretcast的结果未指定,但指针(对应的引用)将在从源类型到目标类型的往返过程中幸存,只要目标类型的对齐要求不比源类型的对齐要求更严格。intx123;unsignedintr1reinterpretcastunsignedint(x);intr2reinterpretcastint(r1);r2456;setsxto456 Onmostimplementations,reinterpretcastdoesnotchangetheaddress,butthisrequirementwasnotstandardizeduntilC11。 在大多数实现中,reinterpretcast不会更改地址,但直到C11,这个要求才被标准化。 reinterpretcastcanalsobeusedtoconvertfromonepointertodatamembertypetoanother,oronepointertomemberfunctiontypetoanother。 reinterpretcast还可用于从一个指向数据成员类型的指针转换为另一个,或从一个指向成员函数类型的指针转换为另一个。 Useofreinterpretcastisconsidereddangerousbecausereadingorwritingthroughapointerorreferenceobtainedusingreinterpretcastmaytriggerundefinedbehaviourwhenthesourceanddestinationtypesareunrelated。 使用reinterpretcast被认为是危险的,因为当源类型和目标类型不相关时,通过使用reinterpretcast获得的指针或引用进行读写可能会触发未定义的行为。 ref: 《NotesForProfessionals》 End