C++中的对象切割(Object slicing)问题

news2024/11/17 20:22:46

 在C++中,当我们把派生类对象向上强制转型为基类对象时,会造成对象切割(Object slicing)问题。
 请看下面示例代码:

#include <iostream>
using namespace std;

class CBase {
public:
	virtual ~CBase() = default;

	virtual void foo() {
		printf("print in Class CBase,this address:%p\n", this);
	}
};

class CDerive : public CBase {
public:
	virtual void foo() override {
		printf("print in Class CDerive,this address:%p\n", this);
	}
};

int main() 
{
	CBase base;
	CDerive derive;
	CBase* pBase = &derive;

	cout << "\n本次调用的是pBase->CBase::foo()\n\t";
	pBase->CBase::foo();

	cout << "\n本次调用的是pBase->foo()\n\t";
	pBase->foo();

	cout << "\n本次调用的是 (static_cast<CBase>(derive)).foo() \n\t";
	(static_cast<CBase>(derive)).foo();
}

 代码运行结果如下:
在这里插入图片描述
 对于前两次调用成员函数foo的结果,大家应该都清楚,pBase是指向派生类对象的基类指针,而foo成员函数是虚函数;因此 pBase->foo() 调用的是派生类方法;pBase->CBase::foo()由于指定了调用CBase的foo函数,因此调用的是基类方法。另外,foo函数打印出来的this指针的地址,显示前两次调用的this指针是同一个,也就是指向子类对象derive。
 关键是最后一次调用的结果,显示调用的是基类方法,并且对象的地址也不是子类对象derive的地址。它的调用语句是:

(static_cast<CBase>(derive)).foo();

 这是为什么呢?这涉及到对象切割(object slicing)。
 在编译时,编译器看到这句是要将派生类对象derive向上强制转为基类对象,因此编译器以所谓的拷贝构造函数把derive中的CBase成分拷贝一份,并把拷贝好的副本作为临时对象放在内存中。在运行期,这个副本(它是CBase对象)调用foo函数时,当然调用的是CBase::foo成员函数了!
 请注意,如果我们把派生类对象的指针向上强制转为基类对象的指针,那么转换后的基类指针仍然指向派生类对象。
 总之,当我们把派生类对象向上强制转型为基类对象时,会经历对象切割(Object slicing),也就是:编译器在内存中创建了一个子类对象的基类成分的副本,这个临时对象与之前的子类对象无关。

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

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

相关文章

nginx交叉编译移植-基于nuc980开发板的笔记

目录 一、nginx的介绍 二、开发环境 三、交叉编译开发过程 四、开发板测试 五、问题 一、nginx的介绍 nginx是一个高性能的Web服务器软件&#xff0c;它可以作为反向代理服务器、负载均衡器、HTTP缓存和安全策略等多种用途。nginx的设计目标是高并发、高性能、高可靠性和低内存…

postgresql中的近一周,近一月,近三月,近一年日期段拆分

统计中经常会遇到,近一周,近一月,近三月,近一年数据统计,下面提供了postgresql拆分日期段的sql -- 近一周,每一天起止时间 select generate_series startDate,generate_series interval 1 day endDate from generate_series( NOW()::date interval -6 day, now()::timest…

揭秘 Go 中的 new() 和 make() 函数

Go&#xff08;或 Golang&#xff09;是一种现代、静态类型、编译型的编程语言&#xff0c;专为构建可扩展、并发和高效的软件而设计。它提供了各种内置的函数和特性&#xff0c;帮助开发人员编写简洁高效的代码。其中包括 new() 和 make() 函数&#xff0c;这两个函数乍看起来…

财务明细一目了然,颜色标记记录轻松掌握个人账目!

无论您是想更好地理清个人收支&#xff0c;还是希望在财务管理中更加高效&#xff0c;我们为您推荐一款绝佳的财政管理神器&#xff1a;颜色标记记录&#xff01; 第一步&#xff0c;首先&#xff0c;我们要先进入【晨曦记账本】主页面&#xff0c;并点击上方功能栏里的“添加…

开发日志:企业微信实现扫码登录(WEB)

一&#xff1a;获取扫码登陆所需的参数&#xff1a;appid,secret,agentid 登录企业微信&#xff1a;https://work.weixin.qq.com/ 扫码登录文档&#xff1a;https://work.weixin.qq.com/api/doc/90000/90135/90988 1&#xff1a;获取appid 点击我的企业就可以看到企业ID信息&am…

【AIGC】如何在使用stable-diffusion-webui生成图片时看到完整请求参数

文章目录 背景开搞使用遇到的问题 背景 通过代码调用Stable Diffusion的txt2img、img2img接口时&#xff0c;很多时候都不知道应该怎么传参&#xff0c;比如如何指定模型、如何开启并使用Controlnet、如何开启面部修复等等&#xff0c;在sd-webui上F12看到的请求也不是正式调用…

java生成验证码返回前端图片,后端通过redis存储和校验

目录 1.导入maven 2.编写config类 3.编写controller 4.验证 1.导入maven <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency> 2.编写config类 …

Mac 文件设置默认展示和排列方式

点击 现在默认展示方式是分栏方式&#xff0c;因我我勾选了 点击这里就可以修改 始终以xx打开&#xff0c;这里我选择了图标视图。 有快捷键 commandJ 修改默认配置。

烟雾文字动画效果

效果展示 CSS 知识点 transform 属性运用transform-origin 属性运用烟雾文字实现 整体页面结构布局实现 <section><p class"text">Lorem ipsum dolor sit amet consectetur adipisicing elit. Vero dolorevoluptas incidunt exercitationem. Consecte…

编程初学者的“天然呆”时光

初学编程的时候&#xff0c;仿佛进入了一个全新的世界&#xff0c;兴奋之余难免迷茫。这个过程中&#xff0c;总是伴随着一些令人哭笑不得的“天然呆”瞬间。本文将回溯我刚开始学写代码时的一些愚蠢但难忘的经历&#xff0c;与读者分享那段独特的学习时光。 一、“Hello Worl…

【pv和pvc】

pv和pvc 一、存在原因二、存储卷分类一、emptyDir存储卷二、hostPath存储卷1.在 node01 节点上创建挂载目录2.在 node02 节点上创建挂载目录3.创建 Pod 资源4.访问测试5.删除pod&#xff0c;再重建&#xff0c;验证是否依旧可以访问原来的内容 三、nfs共享存储卷1.在stor01节点…

UE4 Unlua 初使用小记

function M:Construct()print(Hello World)print(self.Va)local mySubsystem UE4.UHMSGameInstanceSubsystemUE4.UKismetSystemLibrary.PrintString(self,"Get Click Msg From UnLua ")end unlua中tick不能调用的问题&#xff1a; 把该类的Event Tick为灰色显示的删…

Maven 构建配置文件

目录 构建配置文件的类型 配置文件激活 配置文件激活实例 1、配置文件激活 2、通过Maven设置激活配置文件 3、通过环境变量激活配置文件 4、通过操作系统激活配置文件 5、通过文件的存在或者缺失激活配置文件 构建配置文件是一系列的配置项的值&#xff0c;可以用来设置…

【面试经典150 | 哈希表】同构字符串

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;哈希表 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内…

配电运维管理系统:电力数字化升级的关键

随着社会的快速发展和电力需求的增长&#xff0c;配电系统面临着越来越大的压力。为了确保电力供应的稳定性和可靠性&#xff0c;电力企业需要采用先进的管理系统&#xff0c;以提高配电运维的效率和质量。 一、配电运维管理系统的价值 配电运维管理系统通过集成了人工智能…

Nessus安装与使用_nessus安装使用教程

前言&#xff1a; Nessus号称是世界上最流行的漏洞扫描程序&#xff0c;全世界有超过75000个组织在使用它。该工具提供完整的电脑漏洞扫描服务&#xff0c;并随时更新其漏洞数据库。Nessus不同于传统的漏洞扫描软件&#xff0c;Nessus可同时在本机或远端上遥控&#xff0c;进行…

用jad反编译工具查看java接口相关的默认修饰符

接口抽象类复习 -> 默认修饰符是啥 -> jad反编译证明 https://www.cnblogs.com/changrunwei/p/6618117.html 文章目录 背景操作过程反编译前后对比操作截图结论 背景 今天刷到这篇文章&#xff0c;想起之前笔试题总是记不清&#xff0c;所以想证明下。 之前一直不清楚要…

d3dx9_39.dll如何修复?最新修复d3dx9_39.dll方法分享

大家好&#xff01;今天我要和大家分享的主题是“d3dx9_39.dll丢失的修复方法”。我们都知道&#xff0c;在使用电脑的过程中&#xff0c;经常会遇到各种问题&#xff0c;而其中最常见的就是文件丢失。d3dx9_39.dll就是其中一个常见的丢失文件。那么&#xff0c;如何修复这个丢…

Linux|软件安装包deb打包

参考&#xff1a; Ubuntu下的deb打包、安装与卸载 ubuntu打包软件 【Ubuntu】打包C程序及导出依赖库lib 文章目录 导出可执行程序依赖库安装打包工具创建工作目录设定安装的路径编写控制文件使用 dpkg 命令构建 deb包安装 deb包卸载deb包 导出可执行程序依赖库 在.out文件所在…

如何选择适合的Java服务器租用方案

随着共享经济的兴起&#xff0c;租车软件在如今的市场上变得越来越流行。但是&#xff0c;对于许多初创公司和开发者来说&#xff0c;了解开发一个租车软件所需的费用以及如何选择适合的Java服务器租用方案可能是一个挑战。本文将为您提供一些建议&#xff0c;以帮助您了解开发…