《Effective C++》条款27

尽量少做转型动作

class A
{
public:A(int x) :a(x) {};virtual void add(){a++;}
private:int a;
};
class B :public A
{
public:B(int x) :b(x),A(x) {};virtual void add(){static_cast<A>(*this).add();b++;}private:int b;
};

如上描述把子类转型为A类,调用了A::add()。但是它调用的不是当前对象上的函数,而是稍早转型动作所建立的一个"*this对象之base class成分"的暂时副本上的add 。(成员函数只有一份,关键在于成员函数都有一个this指针,会因此影响成员函数操作的数据。)如果add修改了当前对象的内容,当前对象其实没有被改动,被改动的是副本。然而B类里面的add如果也修改对象,那么该对象会被改变。这使当前对象进入一种“伤残”状态:其base class成分的更改没有落实,而derived class成分的更改倒是落实了。

所以请这么写:

class B :public A
{
public:B(int x) :b(x),A(x) {};virtual void add(){A::add();b++;}private:int b;
};

如果想使用dynamic_cast,通常是你想在一个你认定为子类对象身上执行子类操作函数但是你手上只有一个指向基类的指针或引用。你只能靠它们来处理对象。有两个做法可以避免这个问题:

假设子类有一个唯一的函数func

class B :public A
{
public:...void func();...
};

你可以使用容器并在其中存储直接指向子类对象的指针:

typedef vector<shared_ptr<B>> Bptr;
Bptr bp;
...
for (Bptr::iterator iter = bp.begin();iter != bp.end();++iter)
{(*iter)->func();
}

而另一种做法可以让你通过基类接口处理“所有可能之各种A派生类”,那就是在基类内提供virtual函数做到你想对任何派生类做的事:

class A
{
public:virtual void func(){// 什么也不做,缺省}...
};
class B :public A
{
public:virtual void func(){...}...
};
int main()
{typedef vector<shared_ptr<A>> Aptr;Aptr ap;...for (Aptr::iterator iter = ap.begin();iter != ap.end();++iter){(*iter)->func();}
}

这两种做法都可以替代dynamic_cast。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/186108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决keil右键Go To Definition跳转不过去的问题

解决&#xff1a; 在魔法棒中如图所示打上√

rabbitmq技术

1&#xff0c;docker运行rabbitmq docker run --restartalways -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq 2&#xff0c;新增管理员用户 rabbitmq服务&#xff0c;添加用户以及授权_rabbitmq添加用户授权_ROBOT玲玉的博客-CSDN博客

flask web开发学习之初识flask(二)

文章目录 一、创建程序实例并注册路由1. 为视图绑定绑定多个URL2. 动态URL 二、启动开发服务器1. 自动发现程序实例2. 管理环境变量3. 使用pycharm运行服务器4. 更多的启动选项5. 设置运行环境6. 调试器7. 重载器 一、创建程序实例并注册路由 app.py # 从flask包中导入flask类…

NoSQL 数据建模错误会降低性能

数据建模错误是破坏性能的最简单方法之一。当您使用 NoSQL 时&#xff0c;特别容易搞砸&#xff0c;&#xff08;讽刺的是&#xff09;NoSQL 往往用于对性能最敏感的工作负载。NoSQL 数据建模最初可能看起来非常简单&#xff1a;只需对数据进行建模以适应应用程序的访问模式。但…

Elastic Search

ElasticSearch 持续更新中… 选择es的原因 在数据量非常大的时候&#xff0c;业务进行模糊查询会导致索引失效&#xff0c;查询效率低下&#xff0c;使用es进行查询&#xff0c;可以提高查询速度。 text和keyword类型的区别 keyword 类型是不会分词的&#xff0c;直接根据字…

矢量图与位图区别

文章目录 目的区别 目的 了解矢量图与位图区别。 区别 矢量图和位图是两种不同类型的图形图像&#xff0c;它们之间的主要区别在于存储和表示图像的方式&#xff0c;以及在不同应用场景下的优势和劣势。 项目Vector GraphicsBitmap存储方式矢量图使用数学公式和几何图形的描…

linux /proc 文件系统

/proc系统是一个伪文件系统&#xff0c;它只存在内存当中&#xff0c;而不占用外存空间&#xff0c;以文件系统的方式为内核与进程提供通信的接口。 /proc目录下有很多以数字命名的目录&#xff0c;每个数字代表进程号PID它们是进程目录。系统中当前运行的每一个进程在/proc下都…

【C++】异常处理 ② ( 异常捕获类型 | 异常捕获机制 - 严格匹配异常类型 | 未知异常捕获 - 不知道异常类型 )

文章目录 一、异常捕获机制 - 严格匹配异常类型1、异常捕获机制 - 严格匹配异常类型2、代码示例 - 异常捕获严格匹配异常类型 二、异常捕获机制 - 未知异常捕获1、未知异常捕获 - 不知道异常类型2、代码示例 - 未知异常捕获 一、异常捕获机制 - 严格匹配异常类型 1、异常捕获机…

Echarts大屏-数据可视化

使用原生htmljavascript实现大屏展示,较为麻烦的为边框的四个小角使用伪元素生成,其余echarts使用如下快速上手 - Handbook - Apache ECharts 效果如下:

【算法】状压DP-1

状压DP 介绍介绍例子 剖析P4802 [CCO2015] 路短最题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 分析Code 介绍 介绍 状态压缩就是使用某种方法&#xff0c;简明扼要地以最小代价来表示某种状态&#xff0c;通常是用一串01数字&#xff08;二进制数&#xff0…

java论坛数据以及搜索接口实现

一. 内容简介 java论坛数据以及搜索接口实现 二. 软件环境 2.1 java 1.8 2.2 mysql Ver 8.0.13 for Win64 on x86_64 (MySQL Community Server - GPL) 2.3 IDEA ULTIMATE 2019.3 2.4d代码地址 三.主要流程 3.1 创建数据库,创建数据表 3.2 开始编写接口&#xff0c;并测…

几种攻击方式

对抗攻击 Adversarial evasion&#xff08;对抗性逃避&#xff09;是指针对机器学习模型的一种攻击方式&#xff0c;旨在通过对输入数据进行微小但精心设计的修改&#xff0c;使模型产生错误的输出。这种攻击通常是有意识地利用模型的弱点&#xff0c;以便误导模型做出错误的决…

vuepress----1、快速开始

创建项目工程 本文会帮助你从头搭建一个简单的 VuePress 文档。如果你想在一个现有项目中使用 VuePress 管理文档&#xff0c;从步骤 3 开始。 创建并进入一个新目录 mkdir vuepress-starter && cd vuepress-starter使用你喜欢的包管理器进行初始化 yarn init # npm i…

键盘打字盲打练习系列之刻意练习——1

一.欢迎来到我的酒馆 盲打&#xff0c;刻意练习! 目录 一.欢迎来到我的酒馆二.选择一款工具三.刻意练习第一步&#xff1a;基准键位练习第二步&#xff1a;字母键位练习第三步&#xff1a;数字符号键位练习 四.矫正坐姿 二.选择一款工具 工欲善其事必先利其器。在开始之前&…

井盖位移报警器安装,智能化井盖厂家推荐

当井盖发生位移或倾斜时&#xff0c;通常会引起所处道路的安全隐患&#xff0c;给过往的车辆和行人带来许多潜在的危险。为了避免潜在的安全事故频繁出现&#xff0c;及时发现并处理井盖位移或倾斜才能更好的保障人民的安全。因此安装井盖位移报警器是满足政府和市民需求的。 单…

vue项目npm install报错Failed at the fibersa4.0.3 install script

报错如下 解决&#xff1a;降低node版本 降到12.16.0 参考链接

C语言如何格式化字符串

在C语言中&#xff0c;通过使用printf函数来格式化输出字符串。格式化字符串的语法如下&#xff1a; printf("format string", argument1, argument2, ...);其中&#xff0c;format string是格式化字符串&#xff0c; argument1, argument2, … 是要输出的参数。 格…

使用 TypeScript 改进异步操作和错误处理的策略

使用 TypeScript 改进异步操作和错误处理的策略 处理异步代码是 JavaScript 应用程序的主要内容。TypeScript 为异步操作带来类型安全&#xff0c;增强可预测性并减少运行时错误。本文旨在探索我们可以利用的模式来有效地管理异步操作和错误处理。 Async/Await Async/await …

Linux下删除当前目录下的所有目录

Linux下删除当前目录下的所有目录 Linux下删除当前目录下的所有目录&#xff0c;可以使用命令&#xff1a;rm -rf ./* rm -rf ./*可以得知rm -rf ./命令是删除当前目录下的所有文件和文件夹&#xff0c;但不会删除根目录下的文件。其中&#xff0c;".“代表当前目录&…

【加密相册】 隐私协议

【加密相册】隐私协议 1.个人信息的收集和使用 我们的应用程序不会收集用户的个人信息&#xff0c;包括姓名、地址、电子邮件地址、电话号码等。我们不会追踪用户的位置信息或共享用户的个人信息。 2. 非个人化信息的收集和使用 我们的应用程序可能会收集一些非个人化信息&a…