[翻译] Effective C++, 3rd Edition, Item 27: 最少化 casting(强制转型)(下)

Sentaurus TCAD 修改字体 如题 阅读详情

(点击此处,接上篇)

在深入探究 dynamic_cast 的设计意图之前,值得留意的是多数 dynamic_cast 的实现都相当慢。例如,至少有一种通用的实现部分地基于对 class names(类名)进行 string comparisons(字符串比较)。如果你在位于一个 single-inheritance hierarchy(单继承体系)四层深处的一个 object 上执行 dynamic_cast,在这样一个实现下的每一个 dynamic_cast 都要付出相当于四次调用 strcmp 来比较 class names(类名)的成本。对于一个更深的或使用了 multiple inheritance(多继承)的 hierarchy(继承体系),付出的代价会更加昂贵。一些实现用这种方法工作是有原因的(它们不得不这样做以支持 dynamic linking(动态链接))。尽管如此,除了在普遍意义上警惕 casts(强制转型)外,在性能敏感的代码中,你应该特别警惕 dynamic_casts。

对 dynamic_cast 的需要通常发生在这种情况下:你要在一个你确信为 derived class object(派生类对象)上执行 derived class operations(派生类操作),但是你只能通过一个 pointer- or reference-to-base(基类指针或引用)来操控这个对象。有两个普通方法可以避免这个问题。

第一个,直接使用存储着指向 derived class objects(派生类对象)的指针(通常是智能指针——参见 Item 13)的 containers(容器),从而消除通过 base class interfaces(基类接口)操控这个 objects 的需要。例如,如果在我们的 Window/SpecialWindow 继承体系中,只有 SpecialWindows 支持 blinking,对于这样的做法:

class Window { ... };

class SpecialWindow: public Window {
public:
  void blink();
  ...
};
typedef                                            // see Item 13 for info
  std::vector<std::tr1::shared_ptr<Window> > VPW;  // on tr1::shared_ptr

VPW winPtrs;

...

for (VPW::iterator iter = winPtrs.begin();         // undesirable code:
     iter != winPtrs.end();                        // uses dynamic_cast
     ++iter) {
  if (SpecialWindow *psw = dynamic_cast<SpecialWindow*>(iter->get()))
     psw->blink();
}

设法用如下方法代替:

typedef std::vector<std::tr1::shared_ptr<SpecialWindow> > VPSW;

VPSW winPtrs;

...

for (VPSW::iterator iter = winPtrs.begin();        // better code: uses
     iter != winPtrs.end();                        // no dynamic_cast
     ++iter)
  (*iter)->blink();

当然,这个方法不允许你在同一个容器中存储指向全部可能存在的 Window 的 derivatives(派生物)的指针。为了与不同的窗口类型一起工作,你可能需要多个 type-safe containers(类型安全容器)。

一个可以让你通过一个 base class interface(基类接口)操控全部可能存在的 Window 的 derivatives(派生物)的可选方法,就是在这个 base class(基类)中提供让你做你要做的事情的 virtual functions(虚函数)。例如,尽管只有 SpecialWindows 能 blink,在 base class(基类)中声明这个函数,并提供一个什么都不做的缺省实现或许是有意义的:

class Window {
public:
  virtual void blink() {}                       // default impl is no-op;
  ...                                           // see Item 34 for why
};                                              // a default impl may be
                                                // a bad idea

class SpecialWindow: public Window {
public:
  virtual void blink() { ... }                  // in this class, blink
  ...                                           // does something
};

typedef std::vector<std::tr1::shared_ptr<Window> > VPW;

VPW winPtrs;                                    // container holds
                                                // (ptrs to) all possible
...                                             // Window types

for (VPW::iterator iter = winPtrs.begin();
     iter != winPtrs.end();
     ++iter)                                    // note lack of
  (*iter)->blink();                             // dynamic_cast

无论哪种方法——使用 type-safe containers(类型安全容器)或在 hierarchy(继承体系)中上移 virtual functions(虚函数)——都不是到处适用的,但在很多情况下,它们提供了 dynamic_casting 之外的可行的候选方法。当它们可用时,你应该加以利用。

你应该绝对避免的一件东西就是包含了级联 dynamic_casts 的设计,也就是说,看起来类似这样的任何东西:

class Window { ... };

...                                     // derived classes are defined here

typedef std::vector<std::tr1::shared_ptr<Window> > VPW;

VPW winPtrs;

...

for (VPW::iterator iter = winPtrs.begin(); iter != winPtrs.end(); ++iter)
{
  if (SpecialWindow1 *psw1 =
       dynamic_cast<SpecialWindow1*>(iter->get())) { ... }

  else if (SpecialWindow2 *psw2 =
            dynamic_cast<SpecialWindow2*>(iter->get())) { ... }

  else if (SpecialWindow3 *psw3 =
            dynamic_cast<SpecialWindow3*>(iter->get())) { ... }

  ...
}

这样的 C++ 会生成又大又慢的代码,而且很脆弱,因为每次 Window class hierarchy(类继承体系)发生变化,所有这样的代码都要必须被检查,以确认是否需要更新。(例如,如果增加了一个新的 derived class(派生类),在上面的级联中或许就需要加入一个新的条件分支。)看起来类似这样的代码应该总是用基于 virtual function calls(虚函数调用)的某种东西来替换。

好的 C++ 极少使用 casts(强制转型),但在通常情况下完全去除也不实际。例如,第 118 页从 int 到 double 的 cast(强制转型),就是对 cast(强制转型)的合理运用,虽然它并不是绝对必要。(那些代码可以被重写为,声明一个新的 double 类型的变量,并用 x 的值进行初始化。)就像最可疑的结构成分,casts(强制转型)应该被尽可能地隔离,典型情况是隐藏在函数内部,用函数的接口保护调用者远离内部的污秽的工作。

Things to Remember

  • 避免 casts(强制转型)的随时应用,特别是在性能敏感的代码中应用 dynamic_casts,如果一个设计需要 casting(强制转型),设法开发一个 cast-free(没有强制转型)的侯选方案。
  • 如果必须要 casting(强制转型),设法将它隐藏在一个函数中。客户就可以用调用那个函数来代替在他们自己的代码中加入 casts(强制转型)。
  • 尽量用 C++-style casts(C++ 风格强制转型)替换 old-style casts(旧风格强制转型)。它们更容易被注意到,而且他们做的事情也更加明确。
C++ 工程实践(9):数据抽象 陈硕 (giantchen_AT_gmail)http://blog.youkuaiyun.com/Solstice  http://weibo.com/giantchen陈硕关于 C++ 工程实践的系列文章: http://blog.youkuaiyun.com/Solstice/category/8 阅读详情

相关推荐

红外:非均匀性校正01_基本原理与基本方法

非均匀校正(nonuniformity correction,NUC) 基本原理 这里要表达的意思就是:图中每一条直线对应一个像素点的,亮度/辐照度的情况。由于硬件的关系,每一个像素点的线性响应很不一样,所以需要通过矩阵来校正。 校正原理: 一点校正 两点校正 其他原理介绍: 参考链接: 基于多项式拟合的红外焦平面非均匀校正 课件:光电成像——非均匀性校正 红外图像非均匀性校正相关汇总 红外非均匀性校正算法总结 红外图像非均匀矫正——一点矫正 ...

dlvector的博客 2万+

[翻译] Effective C++, 3rd Edition, Item 31: 最小化文件之间的 compilation dependencies(编译依赖)(上)

Item 31: 最小化文件之间的 compilation dependencies(编译依赖)作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/你进入到你的 C++ 程序中,并对一个 class 的 implementation(实现)进行了细微的改变。提醒你

艺术编程 4619

别再手动填序号了!用Python脚本在Arcgis属性表里实现分组自动编号(附完整代码)

本文详细介绍了如何利用Python脚本在Arcgis属性表中实现分组自动编号,告别低效的手工操作。通过核心代码解析和实战教程,帮助GIS工程师快速掌握自动化编号技术,提升工作效率并降低错误率。特别适合城市规划、国土调查等需要处理大量分组数据的场景。

weixin_42532473的博客 309

Effective系列经典著作,铺就程序员殿堂之路

Effective系列图书是我们学习中难以绕开的经典。经典书籍需要不断被重读,因为每一次重读都会带来新的体会。本文带来了5本Effective系列的经典著作,让我们一同迎着大师们的智慧之光,走向卓越。 1 《Effective C++:改善程序与设计的55个具体做法(第三版)中文版(双色)》 Effective C++: 55 Specific Ways to Improve Your Programs and Designs,3/e 【美】Scott Meyers 著 侯捷 译 有人说C++程序员可以

博文视点(北京)官方博客 1044

inferCNV包安装问题及解决办法

InferCNV是一个由broad研究所开发的,利用单细胞转录组数据分析肿瘤细胞拷贝数变异(CNV)的工具。基本思路是在整个基因组范围内,通过计算肿瘤细胞关于参考的“正常”细胞的相对表达,利用滑窗思想对邻近的基因相对表达,计算拷贝数。 先贴一个官方安装说明: 官方infercnv安装说明 安装infercnv包: if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager") BiocManager:

m0_51042606的博客 6803

一文吃透:从零到一开发一套 ABAP RAP 应用的完整路径

ABAP RAP开发实战摘要 本文系统介绍了ABAP RESTful Application Programming Model (RAP)在企业级应用开发中的实施路径。文章以出差申请业务场景为例,详细拆解了RAP开发的六步主线流程: 数据库表设计:规范主键、审计字段设计 CDS数据建模:通过视图定义业务对象实体及关联 行为定义与实现:使用BDEF声明事务规则,Behavior Pool类实现业务逻辑 业务对象投影:裁剪服务接口视图 服务定义与绑定:按OData协议暴露服务 UI集成测试:支持Fiori E

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 509

Effective C++ 3nd 读书摘要(Third Edition 55 Specific Ways to Improve Your Programs and Design)

一、让自己习惯C++ Item1. 视C++为一个语言联邦 C++由以下部分组成:C、Object-Oriented C++、Template C++、STL Item2. 尽量以const、enum、inline代替#define Item3. 尽可能使用const 1.一共有这样几种const用法:char greeting[] = "Hello";

thy专栏 1302

如何在 Linux 上安装 RTX 5090 / 5080 /5070 Ti / 5070 驱动程序 — 详细指南

Linux 上的 NVIDIA 5090 是 AI、游戏和渲染的强大引擎,但需要耐心。如果稳定性是首要考虑因素,请坚持使用开源驱动程序,并关注 NVIDIA 论坛以获取未来更新。

iCloudEnd的博客 6914

[翻译] Effective C++, 3rd Edition, 附录 A. 超越 Effective C++

附录 A. 超越 Effective C++作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/Effective C++ 覆盖了我认为对当前的 C++ 程序员最重要的通用指导方针,但是如果你有兴趣在更多的方面提升你的效力,我推荐你去研读我的其他 C++

艺术编程 6445

36、T5L 迪文屏C51开发之绘制动态曲线

T5L 迪文屏C51开发之绘制动态曲线1、介绍2、例程功能简介3、GUI界面设计3、C51程序设计 1、介绍   本文将利用DGUS Tool软件中的【动态曲线控件】来绘制曲线效果,在T5L迪文屏中总共支持8个通道的曲线,而曲线数据是需要缓冲区的,如果 8 通道曲线同时使用,0x1000-0x4FFF 将作为曲线缓冲区地址,此时该部分变量地址不能被其他控键使用,其他控键地址使用范围为0x5000-0xFFFF,当某曲线通道不被使用时,那么其所对应的缓冲区地址可以做其他用途,曲线通道具体的地址分布如下图所示:

嵌入式羊圈 3133

【即插即用模块】注意力篇 | TGRS 2025 | MFA聚特征+HPDown保细节+HFF融层级,三大模块各司其职,性能翻倍!

本文介绍了MTMLNet网络中的三大核心模块:MFA(多阶段特征聚合)、HPDown(混合池化下采样)和HFF(分层特征融合)。MFA通过双尺度深度卷积和注意力机制增强特征提取能力;HPDown结合平均池化和最大池化,有效保留下采样过程中的特征信息;HFF采用三注意力机制实现自适应特征融合。这三个模块协同工作,在红外小目标检测与分割任务中取得了SOTA效果。实验表明,各模块在特征提取、信息保留和融合方面均优于传统方法,可灵活应用于各类视觉任务中。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 287

[翻译] Effective C++, 3rd Edition, Item 27: 最少化 casting(强制转型)(上)

Item 27: 最少化 casting(强制转型) 作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/C++ 的规则被设计为保证不会发生类型错误。在理论上,如果你的程序想顺利地通过编译,它就不应该试图针对任何 objects 做任何不安全的或无意义的操作。这是

艺术编程 4239

SAP 系统升级不再惧怕 SPAU 与 SPDD:把修改调整做成可控的工程

SAP系统升级中的SPAU/SPDD处理要点:首先明确SPDD处理数据字典对象,SPAU处理程序对象,核心是解决标准对象变更与历史修改的继承问题。关键原则是优先回归标准版本,减少后续升级负担。操作时应利用版本管理对比差异,批量处理可回退对象,并通过F9多选提高效率。对于提示"当前版本与建议一致"的对象直接回归标准。注意区分新旧SPAU界面功能差异,将Note下载移至SNOTE处理,并确保在SPDD/SPAU之后处理SPAU_ENH。最后,所有调整需记录日志并纳入传输请求,确保可追溯性。遵

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 391

[翻译] Effective C++, 3rd Edition, Item 30: 了解 inlining(内联化)的来龙去脉(上)

Item 30: 了解 inlining(内联化)的来龙去脉作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/inline functions ——多么棒的主意啊!它们看起来像 functions,它们产生的效果也像 functions,它们在各方面都比 mac

艺术编程 5420

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

[翻译] Effective C++, 3rd Edition, 附录 B. 第二和第三版之间的 Item 映射

附录 B. 第二和第三版之间的 Item 映射作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/Effective C++ 的第三版在很多方面与第二版不同,其中最引人注目的是它包含很多新的信息。然而,第二版的大部分内容依然保留在第三版中,虽然经常会改变形式和位置

艺术编程 5819

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs - Cover

作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/

艺术编程 3256

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

《effective c++(第三版)》55个具体做法1

做法1

程序的尽头是数学,一日不推导赶不上买买提 210

C# 世界的《Effective C++》,来自.Net之父的核心揭秘

作为.NET程序员,如果只读三本书,那么《框架设计指南:构建可复用.NET库的约定、惯例与模式(第3版)》这本书一定不容错过!

博文视点(北京)官方博客 1137

[翻译] Effective C++, 3rd Edition, Item 3: 只要可能就用 const

Item 3: 只要可能就用 const作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布:http://blog.youkuaiyun.com/fatalerror99/关于 const 的一件美妙的事情是它允许你指定一种 semantic(语义上的)约束:一个特定的 object(对象)不应该被修改。而 compilers(编译器)将执行

艺术编程 6679

Effective C++(Third Edition) Item29 为“异常安全”而努力是值得的

“异常安全”有两个条件:   1、不泄露任何资源     可以通过以对象管理资源的方式(Item13)。   2、不允许数据败坏     异常安全函数提供以下三种保证之一       a、基本承诺         如果异常被抛出,程序内的任何事物都仍然保持在有效状态下,但是何种状态未知。       b、强烈保证         如果异常被抛出,程序状态不改变。       c ...

weixin_30502157的博客 140

深挖C++:类和对象(中)

(先进后出)

xys_678的博客 254

ThunderKittens 深度解析:一个不基于 MLIR 的 C++ 模板 GPU DSL

Triton 是"让更多人能写 GPU kernel",ThunderKittens 是"让会写的人写得更爽"。前者用 MLIR 换易用性,后者用 C++ 模板换可控性。它们不是替代关系,而是覆盖了 GPU 编程光谱的两端。ThunderKittens 的出现,本质上是对"GPU DSL 必须基于 MLIR"这一默认假设的挑战。编译期类型系统本身就可以是一个强大的 DSL 基础设施,不需要中间 IR,不需要黑盒 pass,也能实现 tile 级抽象和零运行时开销。

Maxwell_Newton的博客 349

C++移动构造函数详解

移动构造函数是C++11引入的一种特殊构造函数,用于从临时对象(右值)"窃取"资源来初始化新对象,而不是进行昂贵的深拷贝。char* data;public:// 移动构造函数:参数是右值引用 &&// 关键:把源对象的资源置空。

拒绝AI文,努力在AI时代写出感动人心的好文章 394

跟我学c++中级篇—类型定义的方式

本文系统阐述了编程中类型定义的重要性及c++中的实现方式。重点对比了宏定义、typedef与modern using三种机制,指出using在可读性、灵活性和模板支持上的优势,推荐优先使用。同时提醒开发者注意别名滥用、类型歧义、错误信息冗长等问题,强调统一规范与合理设计。最终结论:在现代c++开发中,应以using为主,兼顾简洁性与可维护性,避免陷入命名混乱与编译困境。

fpcc的专栏 88

【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基

本文系统梳理C++类与对象的核心知识点,涵盖类的定义、访问限定符(public/private)、类作用域、对象实例化及内存布局。重点解析封装思想、this指针机制、空类大小为1字节的原因,以及类与对象在内存中的存储差异。通过对比C语言结构体与C++类,揭示面向对象设计的优势:数据保护、接口统一、命名隔离与代码可维护性提升。内容由浅入深,适合作为学习笔记与复习参考。

2602_95684935的博客 492

C++ 函数模版

模板参数:● template ,T 就是类型占位符,名字可以自定义,习惯用T● 占位符可以在函数返回值、形参、函数内部当作类型使用使用要点模板代码一般写在头文件:编译器需要看到完整模板源码,才能在每个编译单元完成实例化全局函数、类内成员函数都可以写成模板实例化发生在编译阶段,不是运行时隐式实例化:调用时编译器自动推导实参类型,生成对应版本函数。

2501_94041724的博客 307
上一篇: [翻译] Effective C++, 3rd Edition, Item 27: 最少化 casting(强制转型)(上)
下一篇: [翻译] Effective C++, 3rd Edition, Item 28: 避免返回 object 内部构件的 "handles"(“句柄”)
fatalerror99
博客等级 码龄24年 166粉丝 20原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值