大家好,今天小编来为大家解答C++ 核心指南C.146: 如果无法避免类型转换,请使用dynamic_cast这个问题,很多人还不知道,现在让我们一起来看看吧!
dynamic_cast 将在运行时检查。
Example(示例)
struct B { //接口virtual void f();虚空g(); virtual ~B();};struct D : B { //更广泛的接口void f() override; virtual void h( );};void user(B* pb){ if (D* pd=dynamic_castD*(pb)) { //. 使用D 的接口. } else { //. 凑合与B的接口。 }}使用其他强制转换可能会违反类型安全,并导致程序访问实际上属于X 类型的变量,就像访问不相关类型Z: 一样
使用其他类型转换无法确保类型安全,并导致程序将实际上是类型X 的变量访问为类型Z。
void user2(B* pb) //坏{ D* pd=static_castD*(pb); //我知道pb确实指向D;相信我//.使用D 的接口.}void user3( B* pb) //不安全{ if (some_condition) { D* pd=static_castD*(pb); //我知道pb确实指向D;相信我//. 使用D 的接口. } else { //. 凑合使用B 的接口. }}void f(){ B b;用户(b); //确定user2(b); //错误user3(b); //OK * if* 程序员正确地进行了some_condition 检查}
Note(注意)
与其他类型转换一样,dynamic_cast 被过度使用。更喜欢虚函数而不是强制转换。在可能(不需要运行时解析)并且相当方便的情况下,优先选择静态多态性而不是层次结构导航。
与其他类型转换一样,dynamic_cast 被过度使用。最好使用虚函数而不是类型转换。当可能(无需执行时决策)并且更方便时,在继承层次结构中移动时应使用静态多态性。
Note(注意)
有些人在typeid 更合适的情况下使用dynamic_cast; dynamic_cast 是一个通用的“is kind of”操作,用于发现对象的最佳接口,而typeid 是一个“给我该对象的确切类型”操作,用于发现对象的实际类型。后者本质上是一种更简单的操作,应该更快。如果需要的话,后者(typeid)很容易手工制作(例如,如果在由于某种原因禁止RTTI 的系统上工作),则前者(dynamic_cast)通常更难正确实现。
有些人在typeid更合适的时候使用dynamic_cast; dynamic_cast只是一个常见的操作,用于判断一个对象是否属于某种类型,以发现该对象的最佳接口。而typeid就是“告诉我对象的实际类型”的操作,用于获取对象的类型。后者肯定会更简单并且操作应该更快。如果有必要,后者(typeid)更容易自己实现(例如,如果由于某种原因工作系统禁止使用RTTI)一般情况下,前者(dynamic_cast)更难正确实现。
考虑:
struct B { const char* 名称{‘B’}; //if pb1-id()==pb2-id() *pb1 与*pb2 类型相同virtual const char* id() const { return name; } //.};struct D : B { const char* name {‘D’}; const char* id() const override { 返回名称; } //.};void use(){ B* pb1=new B; B* pb2=新D; cout pb1-id(); //’B’ cout pb2-id(); //’D’ if (pb1-id()==’D’) { //看起来很无辜D* pd=static_castD*(pb1); //. } //.}pb2-id()==’D’ 的结果实际上是实现定义的。我们添加它是为了警告自制RTTI 的危险。该代码可能会按预期工作多年,只是在新机器、新编译器或不统一字符文字的新链接器上失败。
pb2-id()==’D’ 的结果实际上是由实现决定的。我们将其作为对自制RTTI 危险的警告。该代码可能会按预期工作很多年,但在新机器、新编译器或没有Unicode 文字的新链接器上会失败。
如果您实现自己的RTTI,请小心。
如果您自己实现RTTI,请小心。
Exception(例外)
如果您的实现提供了非常慢的dynamic_cast,您可能必须使用解决方法。但是,所有无法静态解析的解决方法都涉及显式转换(通常为static_cast)并且容易出错。您基本上将制作自己的专用dynamic_cast。因此,首先确保您的dynamic_cast确实像您想象的那样慢(有很多不受支持的谣言),并且您对dynamic_cast的使用确实对性能至关重要。
如果您的实现提供了非常慢的dynamic_cast,您可能必须解决它。但是,所有解决方法都不是静态可解决的并且容易出错,包括显式类型转换(通常是static_cast)。您只能为特殊目的设计dynamic_cast。因此,首先确认您的dynamic_cast确实像您想象的那样慢(有一些未经证实的谣言),并且您使用dynamic_cast的地方确实对性能敏感。
我们认为当前的dynamic_cast 实现速度过慢。例如,在合适的条件下,可以在快速恒定时间内执行dynamic_cast。然而,即使所有人都同意优化的努力是值得的,兼容性也会使更改变得困难。
我们认为当前的dynamic_cast 实现速度过慢。例如,在适当的条件下,dynamic_cast可以在很短的固定时间内完成。然而,即使每个人都认为优化是有价值的,兼容性也会使更改变得困难。
在极少数情况下,如果您测量到dynamic_cast开销很大,您有其他方法来静态地保证向下转型会成功(例如,您正在谨慎使用CRTP),并且不涉及虚拟继承,请考虑战术上采用static_cast有一个突出的评论和免责声明总结了本段,并且在维护过程中需要人工注意,因为类型系统无法验证正确性。即便如此,根据我们的经验,这种“我知道我在做什么”的情况仍然是已知的错误来源。
例外
考虑(考虑以下代码):
模板类型名称Bclass Dx : B { //.};
Enforcement(实施建议)
标记所有使用static_cast 进行向下转型的情况,包括执行static_cast 的C 风格转型。表示使用static_cast实现向下转换,包括执行static_cast C风格的转换。该规则是类型安全配置文件的一部分。该规则也是类型安全规则组的内容。译者注:
RTTI:运行时类型信息。
CRTP:静态分配。详情请参考:
https://eli.thegreenplace.net/2013/12/05/动态虚拟调用的成本与静态crtp-dispatch-in-c/
原文链接:
原创文章,作者:小su,如若转载,请注明出处:https://www.sudun.com/ask/124412.html
用户评论
无关风月
完全同意这篇文章观点!有时确实会遇到不得不进行类型转换这种情况,动态类型转换虽然麻烦点,但至少比直接强制类型转换安全的多。以后遇到这类问题一定要记住这句准则了。
有10位网友表示赞同!
非想
在实际开发过程中,因为各种原因导致需要类型转换的情况还真不少,这篇博文很有价值,让我对 dynamic_cast 使用更加了解了。之前一直用强制转换,回头来改改还是挺重要的。
有6位网友表示赞同!
蔚蓝的天空〃没有我的翅膀
说的太好了!C++ 的泛型特性很棒,但有时候不得不面对多态带来的挑战,动态类型转换是个很好的解决方案。这篇文章解释得清晰易懂,强烈推荐给那些和我一样还在挣扎于类型转换问题的小伙伴们。
有16位网友表示赞同!
野兽之美
同意使用 dynamic_cast 更安全的观点,但我最近遇到过一个情况,即使使用 dynamic_cast 也导致了程序崩溃… 这种情况下应该如何处理?有没有更高效的方法?
有8位网友表示赞同!
还未走i
我一直觉得C++的指针和引用操作已经够复杂的,现在还要加上dynamic_cast这个转换就更让人头疼了。有没有什么替代方案呢?比如,在编译时就明确类型?
有10位网友表示赞同!
墨城烟柳
这篇文章只是简单描述了动态类型转换的使用方法,并没有深入探讨其背后的原理。我想要了解一下是如何实现类型身份验证的?是通过反射机制还是其他方式?
有12位网友表示赞同!
ˉ夨落旳尐孩。
如果类型转换实在无法避免,那么动态类型转换确实是一个比较好的选择。但需要注意的是,过度依赖动态类型转换可能会降低代码的可读性,而且在复杂场景下也可能带来一些额外的开销。建议多思考,尽量减少类型转换的使用次数。
有15位网友表示赞同!
浅笑√倾城
我平时开发项目的时候,基本都是用强制类型转换,因为它简单快捷方便。但是这篇文章让我意识到安全性和可维护性问题。以后我会尝试使用 dynamic_cast 来替代强制转换,逐步提升代码质量。
有20位网友表示赞同!
凉笙墨染
C++的核心准则总是强调了代码的安全性和可靠性,而 dynamic_cast 在类型转换方面做得确实很好。在学习C++的同时也更要重视这些原则, 避免一些低级错误的发生。
有13位网友表示赞同!
绝版女子
这篇文章让我对动态类型转换有个更深入的理解,它不仅是安全的类型转换方式,还能避免潜在的安全漏洞。我会把这个准则应用到自己的项目中,提高代码质量。
有11位网友表示赞同!
我的黑色迷你裙
在实际工作中,遇到类型转换的情况确实很多,但是使用 dynamic_cast 和强制转换哪个更好? 这篇文章没有给出比较详细的对比分析,希望作者能进一步探讨这个问题,方便我们更好地选择合适的类型转换方式。
有7位网友表示赞同!
醉婉笙歌
我觉得 这篇博文很实用,讲解得很到位, 现在 C++ 的学习越来越重要了。希望以后还有更多这样的文章分享!
有15位网友表示赞同!
淡抹丶悲伤
虽然知道动态类型转换的重要性,但实际应用中还是会遇到一些挑战,比如如何判断类型的正确性,以及如何在复杂场景下使用动态类型转换等等。需要更多相关的文章和实践案例来帮助我们更好地理解和运用它。
有7位网友表示赞同!
余温散尽ぺ
感谢作者的分享!这篇文章让我意识到自己之前使用强制类型转换的习惯需要改变了。从现在开始我将尽力遵循 C++ 的核心准则,优先选择 dynamic_cast 来进行类型转换。
有10位网友表示赞同!
墨染殇雪
虽然动态类型转换能提高代码安全性,但我个人觉得它带来的性能开销还是比较大的。有没有什么其他方法可以兼顾安全性与效率呢?例如使用编译时检查?
有12位网友表示赞同!
╯念抹浅笑
这篇文章让我对 C++ 的核心准则有了一个更深刻的理解。我会将这些准则应用到我的开发实践中,编写更安全、更高效的代码。
有19位网友表示赞同!
掉眼泪
非常感谢作者的文章分享!它帮助我了解了 dynamic_cast 的用法及其背后的原因,我现在更加信心满满地去学习 C++ 了!
有14位网友表示赞同!
来自火星的我
文章内容很棒!希望以后能够更多地分享关于 C++ 核心准则方面的博文,让我能够更好地掌握 C++ 程序的开发技巧。
有9位网友表示赞同!
歆久
(沉默……)
有15位网友表示赞同!