关闭

关闭

关闭

封号提示

内容

首页 More_Effective_C++_简体中文版(pdf_版).pdf

More_Effective_C++_简体中文版(pdf_版).pdf

More_Effective_C++_简体中文版(pdf_版)…

上传者: xlong 2010-12-18 评分 0 0 0 0 0 0 暂无简介 简介 举报

简介:本文档为《More_Effective_C++_简体中文版(pdf_版)pdf》,可适用于IT/计算机领域,主题内容包含MoreEffecitveC作者:ScottMeyers译序、导读:侯捷Item~:ZHCItem~:WQ附:侯捷附:WQ附、附:陈崴译序(侯捷)导符等。

MoreEffecitveC作者:ScottMeyers译序、导读:侯捷Item~:ZHCItem~:WQ附:侯捷附:WQ附、附:陈崴译序(侯捷)导读本书所谈的C惯例与术语臭虫报告意见提供内容更新基础议题ITEMM:指针与引用的区别ITEMM:尽量使用C风格的类型转换ITEMM:不要对数组使用多态ITEMM:避免无用的缺省构造函数运算符ITEMM:谨慎定义类型转换函数ITEMM:自增(INCREMENT)、自减(DECREMENT)操作符前缀形式与后缀形式的区别ITEMM:不要重载“”,“||”,或“,”ITEMM:理解各种不同含义的NEW和DELETE异常ITEMM:使用析构函数防止资源泄漏ITEMM:在构造函数中防止资源泄漏ITEMM:禁止异常信息(EXCEPTIONS)传递到析构函数外ITEMM:理解“抛出一个异常”与“传递一个参数”或“调用一个虚函数”间的差异ITEMM:通过引用(REFERENCE)捕获异常ITEMM:审慎使用异常规格(EXCEPTIONSPECIFICATIONS)ITEMM:了解异常处理的系统开销效率ITEMM:牢记-准则(-RULE)ITEMM:考虑使用LAZYEVALUATION(懒惰计算法)ITEMM:分期摊还期望的计算ITEMM:理解临时对象的来源ITEMM:协助完成返回值优化ITEMM:通过重载避免隐式类型转换ITEMM:考虑用运算符的赋值形式(OP=)取代其单独形式(OP)ITEMM:考虑变更程序库ITEMM:理解虚拟函数、多继承、虚基类和RTTI所需的代价技巧(TECHNIQUES又称IDIOMS或PATTERN)ITEMM:将构造函数和非成员函数虚拟化ITEMM:限制某个类所能产生的对象数量ITEMM:要求或禁止在堆中产生对象ITEMM:灵巧(SMART)指针ITEMM:引用计数ITEMM:代理类ITEMM:让函数根据一个以上的对象来决定怎么虚拟杂项ITEMM:在未来时态下开发程序ITEMM:将非尾端类设计为抽象类ITEMM:如何在同一程序中混合使用C和CITEMM:让自己习惯使用标准C语言附录推荐读物一个AUTOPTR的实现实例在C中计算物件个数(OBJECTSCOUNTINGINC)译者:陈崴为智能指标实作OPERATOR>*(IMPLEMENTINGOPERATOR>*FORSMARTPOINTERS)译者:陈崴译序(侯捷)C是一个难学易用的语言!C的难学不仅在其广博的语法以及语法背後的语意以及语意背後的深层思维以及深层思维背後的物件模型C的难学还在於它提供了四种不同(但相辅相成)的程式设计思维模式:proceduralbasedobjectbasedobjectorientedgenericparadigm。世上没有白吃的午餐。又要有效率又要有弹性又要前瞻望远又要回溯相容又要能治大国又要能烹小鲜学习起来当然就不可能太简单。在如此庞大复杂的机制下万千使用者前仆後续的动力是:一旦学成妙用无穷。C相关书籍之多车载斗量如天上繁星如过江之鲫。广博如四库全书者有之(TheCProgrammingLanguage、CPrimer)深奥如重山复水者有之(TheAnnotatedCReferenceManual,InsidetheCObjectModel)细说历史者有之(TheDesignandEvolutionofC,RuminationsonC)独沽一味者有之(PolymorphisminC,GenericityinC)独树一帜者有之(DesignPatterns,LargeScaleCSoftwareDesign,CFAQs)程式库大全有之(TheCStandardLibrary)另辟蹊径者有之(GenericProgrammingandtheSTL)工程经验之累积亦有之(EffectiveC,MoreEffectiveC,ExceptionalC)。这其中「工程经验之累积」对已具C相当基础的程式员而言有著致命的吸引力与立竿见影的帮助。ScottMeyers的EffectiveC和MoreEffectiveC是此类佼佼HerbSutter的ExceptionalC则是後起之秀。这类书籍的一个共通特色是轻薄短小并且高密度地纳入作者浸淫於COOP领域多年而广泛的经验。它们不但开展读者的视野也为读者提供各种COOP常见问题或易犯错误的解决模型。某些小范围主题诸如「在baseclasses中使用virtualdestructor」、「令operator=传回*this的reference」可能在百科型C语言书籍中亦曾概略提过但此类书籍以深度探索的方式让我们了解问题背後的成因、最佳的解法、以及其他可能的牵扯。至於大范围主题例如smartpointers,referencecounting,proxyclassesdoubledispatching,基本上已属designpatterns的层级!这些都是经验的累积和心血的结晶。我很高兴将以下三本极佳书籍规划为一个系列以精装的形式呈现给您:EffectiveCe,byScottMeyers,AWMoreEffectiveC,byScottMeyers,AWExceptionalC,byHerbSutter,AW不论外装或内容中文版比其英文版兄弟毫不逊色。本书不但与原文本页页对译保留索引并加上精装、书签条、译注、书籍交叉参考、完整范例码、读者服务。这套书对於您的程式设计生涯可带来重大帮助。制作这套书籍使我感觉非常快乐。我祈盼(并相信)您在阅读此书时拥有同样的心情。侯捷于新竹台湾jjhoucccanctuedutwhttp:wwwjjhoucomEffectiveCe和MoreEffectiveC之中译事实上是以ScottMeyers的另一个产品EffectiveCCD为本不仅资料更新同时亦将CD版中两书之交叉参考保留下来。这可为读者带来旁徵博引时的莫大帮助。书中程式多为片段。我将陆续完成完整的范例程式并在VisualC,CBuilder,GNUC上测试。请至侯捷网站(http:wwwjjhoucom)下载。欢迎读者对本书范围所及的主题提出讨论并感谢读者对本书的任何误失提出指正。来信请寄侯捷电子信箱(jjhoucccanctuedutw)。导读对C程式员而言日子似乎有点过於急促。虽然只商业化不到年C却俨然成为几乎所有主要电算环境的系统程式语言霸主。面临程式设计方面极具挑战性问题的公司和个人不断投入C的怀抱。而那些尚未使用C的人最常被询问的一个问题则是:你打算什么时候开始用C。C标准化已经完成其所附带之标准程式库幅员广大不仅涵盖C函式库也使之相形见绌。这么一个大型程式库使我们有可能在不必牺牲移植性的情况下或是在不必从头撰写常用演算法和资料结构的情况下完成琳琅满目的各种复杂程式。C编译器的数量不断增加它们所供应的语言性质不断扩充它们所产生的码品质也不断改善。C开发工具和开发环境愈来愈丰富威力愈来愈强大稳健强固(robust)的程度愈来愈高。商业化程式库几乎能够满足各个应用领域中的写码需求。一旦语言进入成熟期而我们对它的使用经验也愈来愈多我们所需要的资讯也就随之改变。年人们想知道C是什么东西。到了年他们想知道如何运用它。如今C程式员问的问题更高级:我如何能够设计出适应未来需求的软体?我如何能够改善程式码的效率而不折损正确性和易用性?我如何能够实作出语言未能直接支援的精巧机能?这本书中我要回答这些问题以及其他许多类似问题。本书告诉你如何更具实效地设计并实作C软体:让它行为更正确面对异常情况时更稳健强固更有效率更具移植性将语言特性发挥得更好更优雅地调整适应在「混合语言」开发环境中运作更好更容易被正确运用更不容易被误用。简单地说就是如何让软体更好。本书内容分为个条款。每个条款都在特定主题上精简摘要出C程式设计社群所累积的智慧。大部份条款以准则的型式呈现附随的说明则阐述这条准则为什么存在如果不遵循会发生什么後果以及什么情况下可以合理违反该准则。所有条款被我分为数大类。某些条款关心特定的语言性质特别是你可能罕有使用经验的一些新性质。例如条款~专注於exceptions(就像TomCargill,JackReeves,HerbSutter所发表的那些杂志文章一样)。其他条款解释如何结合语言的不同特性以达成更高阶目标。例如条款~描述如何限制物件的个数或诞生地点如何根据一个以上的物件型别产生出类似虚拟函式的东西如何产生smartpointers等等。其他条款解决更广泛的题目。条款~专注於效率上的议题。不论哪一条款提供的都是与其主题相关且意义重大的作法。在MoreEffectiveC一书中你将学习到如何更实效更精锐地使用C。大部份C教科书中对语言性质的大量描述只能算是本书的一个背景资讯而已。这种处理方式意味你应该在阅读本书之前便熟悉C。我假设你已了解类别(classes)、保护层级(protectionlevels)、虚拟函式、非虚拟函式我也假设你已通晓templates和exceptions背後的概念。我并不期望你是一位语言专家所以涉及较罕见的C特性时我会进一步做解释。本书所谈的C我在本书所谈、所用的C是ISOANSI标准委员会於年月完成的C国际标准最後草案(FinalDraftInternationalStandard)。这暗示了我所使用的某些语言特性可能并不在你的编译器(s)支援能力之列。别担心我认为对你而言唯一所谓「新」特性应该只有templates而templates如今几乎已是各家编译器的必备机能。我也运用exceptions并大量集中於条款~。如果你的编译器(s)未能支援exceptions没什么大不了这并不影响本书其他部份带给你的好处。但是听我说纵使你不需用到exceptions亦应阅读条款~因为那些条款(及其相关篇幅)检验了某些不论什么场合下你都应该了解的主题。我承认就算标准委员会授意某一语言特性或是赞同某一实务作法并非就保证该语言特性已出现在目前的编译器上或该实务作法已可应用於既有的开发环境上。一旦面对「标准委员会所议之理论」和「真正能够有效运作之实务」间的矛盾我便两者都加以讨论虽然我其实比较更重视实务。由於两者我都讨论所以当你的编译器(s)和C标准不一致时本书可以协助你告诉你如何使用目前既有的架构来模拟编译器(s)尚未支援的语言特性。而当你决定将一些原本绕道而行的解决办法以新支援的语言特性取代时本书亦可引导你。注意当我说到编译器(s)时我使用复数。不同的编译器对C标准的满足程度各不相同所以我鼓励你在至少两种编译器(s)平台上发展程式码。这么做可以帮助你避免不经意地依赖某个编译器专属的语言延伸性质或是误用某个编译器对标准规格的错误阐示。这也可以帮助你避免使用过度先进的编译器技术例如独家厂商才做得出的某种语言新特性。如此特性往往实作不够精良(臭虫多要不就是表现迟缓或是两者兼具)而且C社群往往对这些特性缺乏使用经验无法给你应用上的忠告。雷霆万钧之势固然令人兴奋但当你的目标是要产出可靠的码恐怕还是步步为营(并且能够与人合作)得好。本书用了两个你可能不甚熟悉的C性质它们都是晚近才加入C标准之中。某些编译器支援它们但如果你的编译器不支援你可轻易以你所熟悉的其他性质来模拟它们。第一个性质是型别bool其值必为关键字true或false。如果你的编译器尚未支援bool有两个方法可以模拟它。第一个方法是使用一个globalenum:enumbool{false,true}这允许你将参数为bool或int的不同函式加以多载化(overloading)。缺点是内建的「比较运算子(comparisonoperators)」如==,<,>=,等等仍旧传回ints。所以以下程式码的行为不如我们所预期:voidf(int)voidf(bool)intx,yf(x<y)呼叫f(int)但其实它应该呼叫f(bool)一旦你改用真正支援bool的编译器这种enum近似法可能会造成程式行为的改变。另一种作法是利用typedef来定义bool并以常数物件做为true和false:typedefintboolconstboolfalse=constbooltrue=这种手法相容於传统的CC语意。使用这种模拟法的程式在移植到一个支援有bool型别的编译器平台之後行为并不会改变。缺点则是无法在函式多载化(overloading)时区分bool和int。以上两种近似法都有道理请选择最适合你的一种。第二个新性质其实是四个转型运算子:staticcast,constcast,dynamiccast,和reinterpretcast。如果你不熟悉这些转型运算子请翻到条款仔细阅读其中内容。它们不只比它们所取代的C旧式转型做得更多也更好。书中任何时候当我需要执行转型动作我都使用新式的转型运算子。C拥有比语言本身更丰富的东西。是的C还有一个伟大的标准程式库(见条款E)。我尽可能使用标准程式库所提供的string型别来取代char*指标而且我也鼓励你这么做。stringobjects并不比char*based字串难操作它们的好处是可以免除你大部份的记忆体管理工作。而且如果发生exception的话(见条款和)stringobjects比较没有memoryleaks(记忆体遗失)的问题。实作良好的string型别甚至可和对应的char*比赛效率而且可能会赢(条款会告诉你个中故事)。如果你不打算使用标准的string型别你当然会使用类似string的其他classes是吧?是的用它因为任何东西都比直接使用char*来得好。我将尽可能使用标准程式库提供的资料结构。这些资料结构来自StandardTemplateLibrary("STL"见条款)。STL包含bitsets,vectors,lists,queues,stacks,maps,sets,以及更多东西你应该尽量使用这些标准化的资料结构不要情不自禁地想写一个自己的版本。你的编译器或许没有附STL给你但不要因为这样就不使用它。感谢SiliconGraphics公司的热心你可以从SGISTL网站下载一份免费产品它可以和多种编译器搭配。如果你目前正在使用一个内含各种演算法和资料结构的程式库而且用得相当愉快那么就没有必要只为了「标准」两个字而改用STL。然而如果你在「使用STL」和「自行撰写同等功能的码」之间可以选择你应该让自己倾向使用STL。记得程式码的重用性吗?STL(以及标准程式库的其他组件)之中有许多码是十分值得重复运用的。惯例与术语任何时候如果我谈到inheritance(继承)我的意思是publicinheritance(见条款E)。如果我不是指publicinheritance我会明白地指明。绘制继承体系图时我对basederived关系的描述方式是从derivedclasses往baseclasses画箭头。例如下面是条款的一张继承体系图:GameObjectSpaceShipAsteroidSpaceStation这样的表现方式和我在EffectiveC第一版(注意不是第二版)所采用的习惯不同。现在我决定使用这种最广被接受的继承箭头画法:从derivedclasses画往baseclasses而且我很高兴事情终能归於一统。此类示意图中抽象类别(abstractclasses例如上图的GameObject)被我加上阴影而具象类别(concreteclasses例如上图的SpaceShip)未加阴影。Inheritance(继承机制)会引发「pointers(或references)拥有两个不同型别」的议题两个型别分别是静态型别(statictype)和动态型别(dynamictype)。Pointer或reference的「静态型别」是指其宣告时的型别「动态型别」则由它们实际所指的物件来决定。下面是根据上图所写的一个例子:GameObject*pgo=pgo的静态型别是GameObject*newSpaceShip动态型别是SpaceShip*Asteroid*pa=newAsteroidpa的静态型别是Asteroid*动态型别也是Asteroid*。pgo=papgo的静态型别仍然(永远)是GameObject*至於其动态型别如今是Asteroid*。GameObjectrgo=*pargo的静态型别是GameObject动态型别是Asteroid。这些例子也示范了我喜欢的一种命名方式。pgo是一个pointertoGameObjectpa是一个pointertoAsteroidrgo是一个referencetoGameObject。我常常以此方式来为pointer和reference命名。我很喜欢两个参数名称:lhs和rhs它们分别是"lefthandside"和"righthandside"的缩写。为了了解这些名称背後的基本原理请考虑一个用来表示分数(rationalnumbers)的class:classRational{}如果我想要一个用以比较两个Rationalobjects的函式我可能会这样宣告:booloperator==(constRationallhs,constRationalrhs)这使我得以写出这样的码:Rationalr,rif(r==r)在呼叫operator==的过程中r位於"=="左侧被系结於lhsr位於"=="右侧被系结於rhs。我使用的其他缩写名称还包括:ctor代表"constructor"dtor代表"destructor"RTTI代表C对runtimetypeidentification的支援(在此性质中dynamiccast是最常被使用的一个零组件)。当你配置记忆体而没有释放它你就有了memoryleak(记忆体遗失)问题。Memoryleaks在C和C中都有但是在C中memoryleaks所遗失的还不只是记忆体因为C会在物件被产生时自动呼叫constructors而constructors本身可能亦配有资源(resources)。举个例子考虑以下程式码:classWidget{}某个class它是什么并不重要。Widget*pw=newWidget动态配置一个Widget物件。假设pw一直未被删除(deleted)。这段码会遗失记忆体因为pw所指的Widget物件从未被删除。如果Widgetconstructor配置了其他资源(例如filedescriptors,semaphores,windowhandles,databaselocks)这些资源原本应该在Widget物件被摧毁时释放现在也像记忆体一样都遗失掉了。为了强调在C中memoryleaks往往也会遗失其他资源我在书中常以resourceleaks一词取代memoryleaks。你不会在本书中看到许多inline函式。并不是我不喜欢inlining事实上我相信inline函式是C的一项重要性质。然而决定一个函式是否应被inlined条件十分复杂、敏感、而且与平台有关(见条款E)。所以我尽量避免inlining除非其中有个关键点非使用inlining不可。当你在本书之中看到一个noninline函式并不意味我认为把它宣告为inline是个坏主意而只是说它「是否为inline」与当时讨论的主题无关。有一些传统的C性质已明白地被标准委员会排除。这样的性质被明列於语言的最後撤除名单因为新性质已经加入取代那些传统性质的原本工作而且做得更好。这本书中我会检视被撤除的性质并说明其取代者。你应该避免使用被撤除的性质但是过度在意倒亦不必因为编译器厂商为了挽留其客户会尽力保存回溯相容性所以那些被撤除的性质大约还会存活好多年。所谓client是指你所写的程式码的客户。或许是某些人(程式员)或许是某些物(classes或functions)。举个例子如果你写了一个Dateclass(用来表现生日、最後期限、耶稣再次降临日等等)任何使用了这个class的人便是你的client。任何一段使用了Dateclass的码也是你的clients。Clients是重要的。事实上clients是游戏的主角。如果没有人使用你写的软体你又何必写它呢?你会发现我很在意如何让clients更轻松通常这会导至你的行事更困难因为好的软体「以客为尊」。如果你讥笑我太过滥情不妨反躬自省一下。你曾经使用过自己写的classes或functions吗?如果是你就是你自己的client所以让clients更轻松其实就是让自己更轻松利人利己。当我讨论classtemplate或functiontemplates以及由它们所产生出来的classes或functions时请容我保留偷懒的权利不一一写出templates和其instantiations(具现体)之间的差异。举个例子如果Array是个classtemplate有个型别参数T我可能会以Array代表此template的某个特定具现体(instantiation)虽然其实Array<T>才是正式的class名称。同样道理如果swap是个functiontemplate有个型别参数T我可能会以swap而非swap<T>表示其具现体。如果这样的简短表示法在当时情况下不够清楚我便会在表示template具现体时加上template参数。臭虫报告意见提供内容更新我尽力让这本书技术精准、可读性高而且有用但是我知道一定仍有改善空间。如果你发现任何错误技术性的、语言上的、错别字、或任何其他东西请告诉我。我会试著在本书新刷中修正之。如果你是第一位告诉我的人我会很高兴将你的大名登录到本书致谢文(acknowledgments)内。如果你有改善建议我也非常欢迎。我将继续收集C程式设计的实效准则。如果你有任何这方面的想法并愿意与我分享我会十分高兴。请将你的建议、你的见解、你的批评、以及你的臭虫报告寄至:ScottMeyerscoEditorinChief,CorporateandProfessionalPublishingAddisonWesleyPublishingCompanyJacobWayReading,MAUSA或者你也可以送电子邮件到mecawlcom。我维护有一份本书第一刷以来的修订记录其中包括错误修正、文字修润、以及技术更新。你可以从本书网站取得这份记录以及其他与本书相关的资讯。你也可以透过anonymousFTP从ftpawlcom的cpmec目录中取得它。如果你希望拥有这份资料但无法上网请寄申请函到上述地址我会邮寄一份给你。这篇序文有够长的让我们开始正题吧。基础议题基础议题。是的pointers(指针)、references(引用)、casts(类型转换)、arrays(数组)、constructors(构造)再沒有比这些更基础的议题了。几乎最简单的C程序也会用到其中大部份特性而许多程序会用到上述所有特性。尽管你可能已经十分熟悉语言的这一部份有时候它们还是会令你吃惊。特别是对那些从C转到C的程序员因为references,dynamiccasts,defaultconstructors及其它nonC性质背后的观念往往带有一股幽暗阴郁的色彩。這一章描述pointers和references的差异並告诉你它们的适当使用时机。本章介绍新的C类型转换(casts)语法並解释为什么新式类型转换法比旧式的C类型转换法优越。本章也检验C的数组概念以及C的多态(polymorphism)概念並说明为什么將这两者混合运用是不智之举。最后本章讨论defaultconstructors(默认构造函数)的正方和反方意见並提出一些建议作法让你回避语言的束缚(因为在你不需defaultconstructors的情況下C也会给你一个。只要留心下面各条款的各项忠告你将向著一個很好的目标迈进:你所生产的软件可以清楚而正确地表現出你的设计意图。ItemM:指针与引用的区别指针与引用看上去完全不同(指针用操作符“*”和“>”引用使用操作符“”)但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针在什么时候使用引用呢?首先要认识到在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象但是该变量在某些时候也可能不指向任何对象这时你应该把变量声明为指针因为这样你可以赋空值给该变量。相反如果变量肯定指向一个对象例如你的设计不允许变量为空这时你就可以把变量声明为引用。“但是请等一下”你怀疑地问“这样的代码会产生什么样的后果?”char*pc=设置指针为空值charrc=*pc让引用指向空值这是非常有害的毫无疑问。结果将是不确定的(编译器能产生一些输出导致任何事情都有可能发生)。应该躲开写出这样代码的人除非他们同意改正错误。如果你担心这样的代码会出现在你的软件里那么你最好完全避免使用引用要不然就去让更优秀的程序员去做。我们以后将忽略一个引用指向空值的可能性。因为引用肯定会指向一个对象在C++里引用应被初始化。stringrs错误引用必须被初始化strings("xyzzy")stringrs=s正确rs指向s指针没有这样的限制。string*ps未初始化的指针合法但危险不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。voidprintDouble(constdoublerd){cout<<rd不需要测试rd,它}肯定指向一个double值相反指针则应该总是被测试防止其为空:voidprintDouble(constdouble*pd){if(pd){检查是否为cout<<*pd}}指针与引用的另一个重要的不同是指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象以后不能改变。strings("Nancy")strings("Clancy")stringrs=srs引用sstring*ps=sps指向srs=srs仍旧引用s,但是s的值现在是"Clancy"ps=sps现在指向ss没有改变总的来说在以下情况下你应该使用指针一是你考虑到存在不指向任何对象的可能(在这种情况下你能够设置指针为空)二是你需要能够在不同的时刻指向不同的对象(在这种情况下你能改变指针的指向)。如果总是指向一个对象并且一旦指向一个对象后就不会改变指向那么你应该使用引用。还有一种情况就是当你重载某个操作符时你应该使用引用。最普通的例子是操作符。这个操作符典型的用法是返回一个目标对象其能被赋值。vector<int>v()建立整形向量(vector)大小为向量是一个在标准C库中的一个模板(见条款M)v=这个被赋值的目标对象就是操作符返回的值如果操作符返回一个指针那么后一个语句就得这样写:*v=但是这样会使得v看上去象是一个向量指针。因此你会选择让操作符返回一个引用。(这有一个有趣的例外参见条款M)当你知道你必须指向一个对象并且不想改变其指向时或者在重载操作符并为防止不必要的语义误解时你不应该使用指针。而在除此之外的其他情况下则应使用指针。ItemM:尽量使用C风格的类型转换仔细想想地位卑贱的类型转换功能(cast)其在程序设计中的地位就象goto语句一样令人鄙视。但是它还不是无法令人忍受因为当在某些紧要的关头类型转换还是必需的这时它是一个必需品。不过C风格的类型转换并不代表所有的类型转换功能。一来它们过于粗鲁能允许你在任何类型之间进行转换。不过如果要进行更精确的类型转换这会是一个优点。在这些类型转换中存在着巨大的不同例如把一个指向const对象的指针(pointertoconstobject)转换成指向非const对象的指针(pointertononconstobject)(即一个仅仅去除const的类型转换)把一个指向基类的指针转换成指向子类的指针(即完全改变对象类型)。传统的C风格的类型转换不对上述两种转换进行区分。(这一点也不令人惊讶因为C风格的类型转换是为C语言设计的而不是为C语言设计的)。二来C风格的类型转换在程序语句中难以识别。在语法上类型转换由圆括号和标识符组成而这些可以用在C++中的任何地方。这使得回答象这样一个最基本的有关类型转换的问题变得很困难:“在这个程序中是否使用了类型转换?”。这是因为人工阅读很可能忽略了类型转换的语句而利用象grep的工具程序也不能从语句构成上区分出它们来。C通过引进四个新的类型转换操作符克服了C风格类型转换的缺点这四个操作符是,staticcast,constcast,dynamiccast,和reinterpretcast。在大多数情况下对于这些操作符你只需要知道原来你习惯于这样写(type)expression而现在你总应该这样写:staticcast<type>(expression)例如假设你想把一个int转换成double以便让包含int类型变量的表达式产生出浮点数值的结果。如果用C风格的类型转换你能这样写:intfirstNumber,secondNumberdoubleresult=((double)firstNumber)secondNumber如果用上述新的类型转换方法你应该这样写:doubleresult=staticcast<double>(firstNumber)secondNumber这样的类型转换不论是对人工还是对程序都很容易识别。staticcast在功能上基本上与C风格的类型转换一样强大含义也一样。它也有功能上限制。例如你不能用staticcast象用C风格的类型转换一样把struct转换成int类型或者把double类型转换成指针类型另外staticcast不能从表达式中去除const属性因为另一个新的类型转换操作符constcast有这样的功能。其它新的C类型转换操作符被用在需要更多限制的地方。constcast用于类型转换掉表达式的const或volatileness属性。通过使用constcast你向人们和编译器强调你通

用户评论(0)

0/200

精彩专题

上传我的资料

每篇奖励 +2积分

资料评价:

/49
仅支持在线阅读

意见
反馈

立即扫码关注

爱问共享资料微信公众号

返回
顶部