记录C++类中的一次函数调用

2023-10-27

引用

之前遇到一次函数调用结果的问题,今天在这里做一下记录。
一个基类,一个派生类,两个类中都有一个函数名相同,参数相同,参数不同的函数,创建基类指针指向派生类对象,调用相应的函数,派生类指针指向基类对象,调用相应的函数,求其输出结果。
具体看下面的示例。

示例

开发环境

visual Studio 2017控制台输出程序。创建项目后自动生成相应的main.cpp文件,本文的代码全部都是在main.cpp中编写。

示例代码

main.cpp

#include <iostream>
using namespace std;

class TransferBase 
{
public:
	//int Fun() { cout << endl; }//无法重载仅按返回值区分的函数Fun()
	void Fun() { cout << "TransferBase::Fun()" << endl; }
	virtual void Fun(int a) { cout << "TransferBase::Fun(int a)" << endl; }
private:
};

class TransferDerived :public TransferBase
{
public:
	void Fun(int a) { cout << "TransferDerived::Fun(int a)" << endl; }//TransferDerived中的Fun(int a)与TransferBase中的Fun(int a)为多态,TransferDerived中的Fun(int a)与TransferBase中的Fun()为隐藏
	void Fun() { cout << "TransferDerived::Fun()" << endl; }//TransferDerived中的Fun()函数与TransferBase中的Fun()函数为隐藏关系
private:

};

int main()
{
	//类之间函数调用
	TransferBase *pBase =  new TransferDerived;
	TransferDerived *pDeri = dynamic_cast<TransferDerived*>(new TransferBase);//“dynamic_cast” : “TransferBase”不是多态类型	,基类指针转换为派生类指针的前提是基类必须有虚函数,否则编译错误;转换失败,派生类指针指向为nullptr

	pBase->Fun();
	pBase->Fun(2);
	//pDeri为nullptr,未转换成功 
	pDeri->Fun();//此句正常执行
	pDeri->Fun(3);//pDeri为nullptr,此句崩溃???
}

上述的代码,使用dynamic_cast将基类指针强转为派生类指针失败,其指针pDeri为空,运行pDeri->Fun(3);时出现崩溃,但是为什么在执行pDeri->Fun();的时候能正常执行呢???
原因:纯属意外。

dynamic_cast使用注意事项

1.用于类类型之间的强转。一般用于将基类指针转换为派生类指针,或将派生类指针转换为基类指针,但是将基类指针转换为派生类指针有一个前提:基类中必须要有虚函数
2.指针强转失败,返回值为nullptr.
上述main函数中创建派生类指针指向基类对象,一开始没有在基类中编写虚函数,因而编译的时候无法通过,在基类中增加了虚函数之后,TransferDerived pDeri = dynamic_cast<TransferDerived>(new TransferBase);才能编译通过。但上述派生类指针指向依旧为空,也就是基类的对象并没有强转成功。
其没转换成功的原因是:派生类继承自基类,含有基类的一些函数,可以自动转换为基类,而基类是不含有派生类中的函数,开辟的内存无法满足派生类的内存,直接访问会导致内存越界,故而无法直接转换为派生类。

为了使基类的对象转换为派生类对象,这时需要做下面的一些修改。

修改后的示例代码

上述使用dynamic_cast后没有成功将基类对象转换为派生类对象,这里先将基类的指针指向派生类对象,后将指向派生类对象的指针强转为派生类指针。下面是改动后的代码:

int main()
{
//类之间函数调用
	TransferBase *pBase =  new TransferDerived;
	TransferDerived *pDeri = dynamic_cast<TransferDerived*>(new TransferBase);//“dynamic_cast” : “TransferBase”不是多态类型	,基类指针转换为派生类指针的前提是基类必须有虚函数,否则编译错误;转换失败,派生类指针指向为nullptr

	//使基类指针转换为派生类指针转换成功——先将基类指针指向派生类对象,再将基类指针转换为派生类指针
	TransferDerived derive;
	TransferBase *base = &derive;
	pDeri = dynamic_cast<TransferDerived*>(base);//pDeri不为nullptr,基类指针转换为派生类指针成功

	//转换成功,pDeri不为nullptr
	pBase->Fun();
	pBase->Fun(2);
	pDeri->Fun();
	pDeri->Fun(3);
}

运行结果

在这里插入图片描述

总结

上述涉及到的知识点:
1.虚函数的使用;
2.隐藏、重载、重写的区别;
3.数据强转dynamic_cast.
以上是此篇文章需要具备的知识点。本文仅以记录。有关隐藏、重载、重写的介绍可以查看我之前的文章进行了解。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

记录C++类中的一次函数调用 的相关文章

  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 基于范围的 for 循环中的未命名循环变量?

    有没有什么方法可以不在基于范围的 for 循环中 使用 循环变量 同时也避免编译器发出有关未使用它的警告 对于上下文 我正在尝试执行以下操作 我启用了 将警告视为错误 并且我不想进行像通过在某处毫无意义地提及变量来强制 使用 变量这样的黑客
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • 可空属性与可空局部变量

    我对以下行为感到困惑Nullable types class TestClass public int value 0 TestClass test new TestClass Now Nullable GetUnderlyingType
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz

随机推荐

  • 检查处理kettle数据流中的空行

    检查处理kettle数据流中的空行 ETL处理过程中 有时需要生成数据 但是却没有输入数据 这可能有一些问题 所以通常需要ETL数据流产生一个空行数据 有时处理中需要一些聚集功能 则意味着当没有输入数据时 生成值为0 本文说明怎样检测并处理
  • 国产linux操作系统深度系统20.3发布(推荐)

    深度操作系统 deepin 是一个致力于为全球用户提供美观易用 安全稳定服务的Linux发行版 同时也一直是排名最高的来自中国团队研发的Linux发行版 了解deepin国际排名 深度操作系统20 3 升级Stable内核到5 15版本 进
  • 学习笔记-无向图的创建、深度优先遍历、广度优先遍历

    图 为什么要有图 线性表局限于一个直接前驱和一个直接后继的关系 树也只能有一个直接前驱也就是父节点 当我们需要表示一种多对多的关系就需要用到图 图是一种数据结构 其中结点可以具有零个或多个相邻元素 两个结点之间的连接称为边 结点也可以称为顶
  • 机器学习:Logistic回归介绍

    Logistic回归定义 简单来说 逻辑回归 Logistic Regression 是一种用于解决二分类 0 or 1 问题的机器学习方法 用于估计某种事物的可能性 比如某用户购买某商品的可能性 某病人患有某种疾病的可能性 以及某广告被用
  • 【转载】Java Instrument 功能使用及原理

    0 介绍 利用 java lang instrument 做动态 Instrumentation 是 Java SE 5 的新特性 它把 Java 的 instrument 功能从本地代码中解放出来 使之可以用 Java 代码的方式解决问题
  • elasticsearch FunctionScore Java API

    elasticsearch FunctionScore java API 1 使用script FunctionScoreQueryBuilder query QueryBuilders functionScoreQuery queryBu
  • 修改微信小程序官方picker-view日期选择器

    微信小程序问题之picker view日期选择器 项目需求截图 选择出生日期的时候需要用到微信的picker view日期选择器 然后就发现官方picker view组件有一些问题 1 初始化日期不是当前日期 2 选择不同月份 日期都是从1
  • NVIDIA Video Codec SDK简介

    NVIDIA的Video Codec SDK提供API对视频进行加速编解码 最新发布版本为12 0 支持Windows和Linux平台 可从 https developer nvidia com video codec sdk archiv
  • python 操作 doc /docx

    对于python来说操作 doc 需要用到 win32com 安装 pip install win32com 优点 doc所有的操作都可以执行 缺点 如果没有office就死翘翘了 当然也可以com wsp 对于这种需要强制安装xx的不是很
  • Redis系列(一)与同类对比,底层数据结构,阿里云简单部署

    Redis与Memcache Ehcache对比 有持久化需求或者对数据结构和处理有高级要求的应用 选择redis 其他简单的key value存储 选择memcache Memcache适合多读少写 大数据量的情况 如人人网大量查询用户信
  • Docker搭建rtmp视频直播

    一 PC端搭建RTMP服务器 1 安装docker sudo apt get install docker sudo apt get update 2 下载docker nginx rtmp容器 sudo apt get install d
  • html中如何获取表单的数据

    1 使用表单中的id属性获取表单中的数据 在表单的input标签中指定id属性值 在script脚本中可以通过 表格的名称 id名称 value 来访问表单中的值 例如 register form username value 表单代码
  • 整理最新java面试宝典2019

    java面试宝典2019 参照 http www wityx com 3 html 1 meta标签的作用是什么 2 ReenTrantLock可重入锁 和synchronized的区别 总结 3 Spring中的自动装配有哪些限制 4 什
  • 用U盘安装Linux系统

    需要的东西 1 软件 Universal USB Installer 2 U盘 容量至少为4GB 3 linux系统的镜像文件 比如 ubuntu 10 04 3 desktop i386 iso或者ubuntu 10 04 desktop
  • 在排序数组中查找元素的第一个和最后一个位置

    本文就来探究几个最常用的二分查找场景 寻找一个数 寻找左侧边界 寻找右侧边界 而且 我们就是要深入细节 比如不等号是否应该带等号 mid 是否应该加一等等 分析这些细节的差异以及出现这些差异的原因 保证你能灵活准确地写出正确的二分查找算法
  • Alibaba 神器!一招定位 线 上Bug

    尊重原创版权 https www csnovel com hot 43764 html 更多内容参考 https www csnovel com 阿里神器 一招定位 线 上Bug 背景 公司有个渠道系统 专门对接三方渠道使用 没有什么业务逻
  • windows计算机锁屏的快捷键是什么,win10电脑锁屏快捷键是什么

    我们在使用win10操作系统的时候 其中有很多快捷方式我们都是可以直接使用键盘操作而省去鼠标键盘配合操作的 这样做的优点就是会非常的有效率 节省时间而且没有繁琐的步骤 有的小伙伴想知道我们win10的锁屏快捷键是什么 那么现在就让小编来告诉
  • 杰理之蓝牙OTA蓝牙升级【篇】

    命令AT OTA r响应成功 r nOK r n失败 r nERR data r n
  • gitee码云的使用 ----- 将项目上传

    准备工作 首先你得安装好git 安装教程如下 https git scm com downloads 去码云官网注册登录 然后创建仓库按照步骤做完会得到一个https地址 然后下面就会用到 接下来就是如何将自己的项目代码放置到gitee上
  • 记录C++类中的一次函数调用

    引用 之前遇到一次函数调用结果的问题 今天在这里做一下记录 一个基类 一个派生类 两个类中都有一个函数名相同 参数相同 参数不同的函数 创建基类指针指向派生类对象 调用相应的函数 派生类指针指向基类对象 调用相应的函数 求其输出结果 具体看