Guru of the Week 条款17:转型

原创 2001年12月18日 09:26:00

GotW #17 Casts<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

著者:Herb Sutter

翻译:K ][ N G of @rk™

[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著作权归原著者本人所有。译者kingofark在未经原著者本人同意的情况下翻译本文。本翻译内容仅供自学和参考用,请所有阅读过本文的人不要擅自转载、传播本翻译内容;下载本翻译内容的人请在阅读浏览后,立即删除其备份。译者kingofark对违反上述两条原则的人不负任何责任。特此声明。

 

Revision 1.0

 

Guru of the Week 条款17:转型

 

难度:6 / 10

 

(你对C++转型了解多少?适当的使用它可以极大的提高代码的可靠性。)

 

 

[问题]

标准C++中新风格的转型与旧风格的C转型相比,具有更强大的功能和安全性。你对它了解多少?本条款中使用下列类和全局变量:

1.  下列哪一种新风格的转型不能与C中的转型相对应?

const_cast

dynamic_cast

reinterpret_cast

static_cast

 

2.  对于下列每一个C中的转型语句,写出相应的新风格转型语句。其中哪一个语句如果不以新风格编写的话就是不正确的?

3.  评判下列每一条C++转型语句的编写风格和正确性。

 

[解答]

 

1.  下列哪一种新风格的转型不能与C中的转型相对应?

 

只有dynamic_cast不能与C的转型相对应。其它的新风格转型都能与C中的旧风格转型相对应。

 

2.  对于下列每一个C中的转型语句,写出相应的新风格转型语句。其中哪一个语句如果不以新风格编写的话就是不正确的?

应该使用const_castconst_cast<A*>(&ra1);

这一句无法以新风格的转型表达。最接近的方案是使用const_cast,但a2是一个const object,语句执行的结果是未定义的。

应该使用reinterpret_castpb=reinterpret_cast<B*>(&c1);

这一转型在C中是错误的。而在C++中,并不需要转型:pc=&d1;

 

3.  评判下列每一条C++转型语句的编写风格和正确性。

 

首先要注意:我们并不知道本条款中给出的类是否拥有虚拟函数;如果涉及转型的那些类并不拥有虚拟函数,那么下述所有对dynamic_cast的使用都是错误的。在下面的讨论中,我们假设所有的类都拥有虚拟函数,从而使所有的dynamic_cast用法都合法。

错误:对两条语句我们都必须使用reinterpret_cast。这一开始或许会使你感到吃惊;这样做的原因是,charsigned char以及unsigned char是三个互不相同、区别开来的型别。尽管它们之间存在着隐式转换,它们也是互无联系的,因而指向它们的指针也是互无联系的。

这两句都不错,但第一句中的转型是不必要的,因为本来就有从一个对象指针到void*的隐式转型动作存在。

这一句不错,但其转型也是不必要的,因为其引数(argument)已经是一个B*

这一句是合法的,但是使用转型来去掉const-ness(常量性)是潜在的不良风格的体现。在大部分情况下,即当你因合理的缘由而想要去掉指针或引用的const-ness(常量性)时,这都涉及到某些类成员,并通常会使用mutable关键字来完成。请参看GotW#6了解更多关于const-correctness的讨论。

错误:如果该指针被用来对对象施行写操作,那么就会产生未定义行为;因为a2是一个const object。要明白其原因,可以试想如果一个编译器了解到“a2是作为const object而被创建的”这个情况,并出于优化的考虑而将其存放在只读存储区,会发生什么事情。很明显,想通过转型而去掉这样一个对象的const属性是危险的。

 

注意:我并没有举例显示如何使用const_cast把一个non-const指针转型为一个const指针。因为这样做是多此一举;将一个non-const指针赋值给一个const指针,这本来就是合法的。我们只需要使用const_cast做相反的操作。

错误(当你企图使用pb3时发生):这一句会将pb3设置为null,因为c1不是一个(IS-NOT-AB(因为C不是以public方式派生自B的,且实际上压根儿就不是派生自B的)。这里唯一合法可用的转型就是reinterpret_cast,但使用它也几乎总是很龌龊的。

错误:这一句是非法的,因为b1不是一个(IS-NOT-AA(因为B不是以public方式派生自A的,而是以private方式)。

这一句不错,但也没必要做转型,因为derived-to-base(由派生类到基类)的指针转换可以被隐式的完成。

这一句不错。如果你原先认为这里需要的是dynamic_cast的话,这或许会使你感到吃惊。其原因是,当目标已知的时候,向下转型(downcast)可以是静态的,此时要注意:你这样等于是在告诉编译器,你知道“被指针所指的正是那种型别”这个事实。如果你错了,那么这个转型将无法告知你已经出现的问题(dynamic_cast在转型失败时就能返回一个null pointer以告知你出现了问题),于是你此时至多也只能得到各种不同的运行期错误以及/或者程序崩溃。

这两句看起来很相似。两句都试图使用dynamic_cast来把B*转换为A*。然而,第一个是错误的而第二个是正确的。

 

原因是:正如前面所述,你不能使用dynamic_cast把一个指向B对象(这里pb2指向对象b1)的指针转换为指向A对象的指针,因为B是以private方式从A进行继承的,不是以public方式。然而第二句中的转型是成功的,这是因为pb4指向对象d1,而D(通过C)将A作为一个间接的public base class,从而让dynamic_cast可以沿着B*-->D*-->C*-->A*的路径在继承层次结构中进行转型。

这一句也不错,其原因与上面的一样:dynamic_cast可以穿越继承层次进行交叉转型(cross-cast),因此这一句是合法的并可以成功执行。

最后这一句是错的……因为*pb2并不真的就是一个Cdynamic_cast会抛出一个bad_cast异常来报告失败。为什么?因为dynamic_cast可以在指针转型(pointer cast)失败时返回null,但由于没有null reference一说,因此当一个引用转型(reference cast)失败时便无法返回null reference。除了抛出一个异常以外,没有别的方法来报告错误了——标准的bad_cast异常类也就是因此而来的。

(完)

Guru of the Week 条款17:转型

GotW #17 Casts著者:Herb Sutter翻译:K ][ N G of @rk™[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著作权归原...
  • hejishan
  • hejishan
  • 2008年04月08日 23:41
  • 185

Guru of the Week 条款19:自动转换

GotW #19 Automatic Conversions著者:Herb Sutter翻译:K ][ N G of @rk™[声明]:本文内容取自www.gotw.ca网站上的Guru of the...
  • kingofark
  • kingofark
  • 2001年12月24日 13:38
  • 1127

Guru of the Week 条款14:类之间的关系(上篇)

GotW #14 Class Relationships Part I著者:Herb Sutter     翻译:kingofark[声明]:本文内容取自www.gotw.ca网站上的Guru of ...
  • kingofark
  • kingofark
  • 2001年10月29日 20:05
  • 1111

Guru of the Week 条款25:auto_ptr

GotW#25 auto_ptr难度:8/10问题考虑下面的代码:那些是好的,那些是安全的,那些是合法的, 那些是非法的?auto_ptr source() { return new T(1); } ...
  • taodm
  • taodm
  • 2002年08月05日 10:20
  • 1153

Guru of the Week 条款02: 临时对象

GotW #02 Temporary Objects著者:Herb Sutter      翻译:kingofark[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week...
  • kingofark
  • kingofark
  • 2001年10月23日 20:08
  • 1004

Guru of the Week 条款00:kingofark和Guru of the Week

 Revision 1.0Guru of the Week 条款00:kingofark和Guru of the Week作者:kingofark难度:0 / 10(本条款是GotW的译者kingof...
  • kingofark
  • kingofark
  • 2001年10月24日 13:48
  • 1039

Guru of the Week 条款13:面向对象程序设计

GotW #13 OOP著者:Herb Sutter      翻译:kingofark[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著作权归原著者本人所...
  • kingofark
  • kingofark
  • 2001年10月24日 08:49
  • 1141

Guru of the Week 条款18:Iterators(迭代子)

GotW #18 Iterators著者:Herb Sutter翻译:K ][ N G of @rk™[声明]:本文内容取自www.gotw.ca网站上的Guru of the Week栏目,其著...
  • hejishan
  • hejishan
  • 2008年04月08日 23:40
  • 165

Guru of the Week 条款24:编译级防火墙

[CAT*G Translation Project GotW#22-30: Draft]GotW #24 Compilation Firewalls著者:Herb Sutter翻译:CAT*G[声明...
  • kingofark
  • kingofark
  • 2002年02月06日 14:52
  • 1080

Guru of the Week 条款30附录:接口原则

(至此,GotW1~30即《Exceptional C++》的原型,补全。)Herb Sutter在March 1998于C++ Report上发表的文章《Whats In a Class - The...
  • taodm
  • taodm
  • 2002年08月05日 10:13
  • 1285
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Guru of the Week 条款17:转型
举报原因:
原因补充:

(最多只允许输入30个字)