C++57个入门知识点_47 虚函数的多态性(成员函数中的虚函数具有多态性;构造和析构函数中,虚函数没有多态性;在构造析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,没有多态)

2023-11-17

本篇主要讨论两个问题:

1.成员函数中,虚函数是否有多态性?答案为:有;
2.构造和析构函数中,虚函数是否有多态性?答案为:无。

1.成员函数中,虚函数是否有多态性?


成员函数中的虚函数具有多态性。

以下代码中 void test() { foo(); }普通成员函数中,调用的foo();是否具有多态性(间接调用)?

p->test();处设置断点,单步运行

#include <iostream>

class CParent
{
public:

	virtual void foo() {
		printf("void CParent::foo()\r\n");
	}

	//普通成员函数中,调用的foo具有多态性(间接调用,看虚表)
	void test() {
		foo();
	}
};

class CMyclass :public CParent
{
public:
	CMyclass() {}

	virtual ~CMyclass() { }

	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

int main(int argc, char* argv[])
{
	//儿子对象的指针赋值给父亲
	CParent* p = new CMyclass;//儿子的内容包含父亲所有内容,指针访问安全

	p->test();

	return 0;
}

运行结果:void test() { foo(); }普通成员函数中,调用的foo()是子类的函数,属于间接调用,具有多态
在这里插入图片描述
因此:普通成员函数中,调用的foo()是具有多态性(间接调用,看虚表)

2.构造和析构函数中,虚函数是否有多态性?


构造和析构函数中,虚函数没有多态性

以下代码中CParent* p = new CMyclass;先会调用子类CParent构造函数,此时父类构造函数中的foo();如果存在多态就会调用子类的函数,但是此时子类的还没有构造好,是无法调用的,因此调用的是父类的foo();函数。

#include <iostream>

class CParent
{
public:
	CParent() {
		foo();
	}
	virtual ~CParent() {

	}
	virtual void foo() {
		printf("void CParent::foo()\r\n");
	}

	void test() {
		foo();
	}
};

class CMyclass :public CParent
{
public:
	CMyclass() {
		foo();
	}
	virtual ~CMyclass() {

	}
	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

int main(int argc, char* argv[])
{

	CParent* p = new CMyclass;

	return 0;
}

运行结果:调用父类的函数,不属于间接调用,不具有多态性
在这里插入图片描述
因此在构造函数中调用虚函数,实际上是直接调用,所以没有多态

3.析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用


在构造析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,由于进入构造时,会为对象赋值为当前类的虚表,所以没有多态。

如果将上述两种情况结合,构造函数中包含test()函数,test()函数中包含foo();函数,

#include <iostream>

class CParent
{
public:
	CParent() {
		test();
	}
	virtual ~CParent() {

	}
	virtual void foo() {
		printf("void CParent::foo()\r\n");
	}

	void test() {
		foo();
	}
};

class CMyclass :public CParent
{
public:
	CMyclass() {
		foo();
	}
	virtual ~CMyclass() {

	}
	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

int main(int argc, char* argv[])
{

	CParent* p = new CMyclass;

	return 0;
}

运行结果: CParent() { test();}中调用父类中的foo();,不存在多态
在这里插入图片描述
在析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,由于进入构造时,会为对象赋值为当前类的虚表,所以没有多态。
在这里插入图片描述
同理当test();是在子类的构造函数中

class CMyclass :public CParent
{
public:
	CMyclass() {
		test();
	}
	virtual ~CMyclass() {

	}
	virtual void foo() {
		printf("void CMyclass::foo()\r\n");
	}

};

运行结果:调用子类的函数
在这里插入图片描述

4.学习视频地址:C++57个入门知识点_47 虚函数的多态性

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

C++57个入门知识点_47 虚函数的多态性(成员函数中的虚函数具有多态性;构造和析构函数中,虚函数没有多态性;在构造析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,没有多态) 的相关文章

随机推荐

  • Visual Studio error C2001:常量中有换行符

    问题描述 问题分析 经百度多方求助 发现该问题主要是由中文和文件编码格式引起的 存在中文时需要手动文件编码格式转换成UTF 8 这里使用Notepad 去转换 但是很奇怪的是我发现我的文件就是UTF 8的格式 仍然编译不过 我查询了其他没有
  • idea插件生成用例图、时序图、类图、活动图

    给大家推荐一个idea生成用例图 时序图等的神器 PlantUML 最近软件工程要结课了 结课报告要附加用例图 时序图 类图 活动图等 类图我首先就想到可以用idea生成 嘿嘿 可惜忘了怎么用 搜着搜着 突然发现 idea生成时序图 用例图
  • dfs、bfs时候染色算法和直接传一个visited两种方法

    以695 岛屿的最大面积为例 在图的遍历中 如果不加任何约束 DFS和BFS一定会遍历到重复节点 解决这个问题的一个方法就是在函数外定义一个visited set 然后每次遍历的时候把未在visited中的节点加入 在外面的递归终止条件 队
  • eclipse 项目没错却有红叉(解决办法)

    1 进入 eclipse 选择报错的项目 然后在工具栏选择Window 选择Show View 选择Problems 如下图 2 找到 General 下的 problems 双击 problems 就会在下面提示你项目报错的原因 根据错误
  • Go_异常处理

    Error 异常就是程序出现了不正常的情况 会导致程序非正常停止 而异常处理就是针对非正常停止的情况 给出异常时的处理方式 语法错误不算异常体系中 error是一个接口 作用是返回程序异常的信息 errors实现了error type er
  • QT踩坑第十一天(QT多线程)

    前言 QT在什么时候会用到多线程 所有的IO操作都要放到线程里面 1 IO操作QIODevice文件IO网络IO 套接字eg CAN Linux下也是套接字 串口等外设 因为他们不确定什么时候可以读完 2 耗时的算法eg 文件压缩 信号处理
  • Moviepy音视频开发:视频转gif动画或jpg图片exe图形化工具开发案例

    前往老猿Python博文目录 一 引言 老猿之所以学习和研究Moviepy的使用 是因为需要一个将视频转成动画的工具 当时在网上到处搜索查找免费使用工具 结果找了很多自称免费的工具 但转完GIF后都会在动画中打上对应工具的显著广告或Logo
  • 一周小结 - 拒绝拖延 现在做起

    很早就一直有用文字记录生活的想法 终于在这周开始了 不知道能写多久 拭目以待 一周的生活回顾下来 可能下面的一些让自己有些许感悟吧 感悟之一 更多的体验发现不一样的美好 感悟之二 有些事并没那么可怕 可怕的 可能是被头脑放大了N倍 感悟之三
  • 华为od机试 Python【扩散矩阵】

    描述 你手上有一个数字版的迷宫 里面只有两种格子 0 和 1 这里的1有个特性 它每秒会感染它上 下 左 右的0格子 一旦0被感染 它就变成1 给定一个迷宫大小以及两个起始感染点 你能算出这个迷宫被完全感染需要多少秒吗 输入 迷宫的行列数
  • mybatis-plus返回查询总记录数

    mybatis plus返回查询总记录数 mp框架提供了selectCount方法 来查询总记录数 需求 查找薪水大于3500 名字里有 小 的 员工的个数 sql实现 select count from t employee where
  • C++的基础学习

    C 主要学习 C与C 的不同 C 的特性及专业术语 C 程序的编译 一 C到C 的转换 C与C 的区别 C 是C的增强 区别 C 具有严格的数据类型检查 C 新增了命名空间 异常处理 面向对象编程 变量的权限和引用及函数的重载及运算符的重载
  • HTTP1.0和HTTP1.1和HTTP2.0的区别

    HTTP1 0和HTTP1 1和HTTP2 0的区别 1 HTTP1 0和HTTP1 1的区别 1 1 长连接 Persistent Connection HTTP1 1支持长连接和请求的流水线处理 在一个TCP连接上可以传送多个HTTP请
  • Mysql索引详解及优化(key和index区别)

    Mysql索引详解及优化 key和index区别 文章记录
  • Hyperledger Fabric配置文件解析

    目录 1 相关配置文件介绍 2 crypto config yaml 3 configtx yaml 3 1 Organizations组织配置部分 3 2 Capabilities通道能力配置部分 3 3 Application 应用通道
  • 浏览器内核css前缀大全

    1 css前缀为 moz 的浏览器 火狐浏览器 2 css前缀为 webkit 的浏览器 谷歌浏览器 苹果浏览器 Comodo Drangon 科摩多龙 搜狗高速浏览器 快快浏览器 枫树浏览器 云游浏览器 360极速浏览器 世界之窗极速版
  • RedmiBook 蓝屏 关机后出现 No Bootable Devices 问题的解决方法

    问题 关机后 重新开机出现 显示 没有可启用设备 解决方法一 该方法解决的不够彻底 暂时可以解决问题 正常开机 关机后 按f2 开机键 出现以下页面 选择 启动菜单 gt 启动模式 gt UEFI 启动 gt Enter 选择 退出菜单 g
  • 嵌入式毕业设计 树莓派寝室宿舍门禁刷卡系统 - 物联网 单片机 嵌入式

    文章目录 0 前言 1 前言 2 主要器件 3 实物效果 4 树莓派读取 RC522 RFID 标签 5 mg90s 控制原理 6 最后 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕
  • 为什么使用非线性激活函数?常见的非线性激活函数及优缺点对比

    为何使用非线性激活函数 如上图的神经网络 在正向传播过程中 若使用线性激活函数 恒等激励函数 即令 则隐藏层的输出为 即 可以看到使用线性激活函数神经网络只是把输入线性组合再输出 所以当有很多隐藏层时 在隐藏层使用线性激活函数的训练效果和不
  • js实现滑动拼图验证码

    js实现滑动拼图验证码 我这个样式是仿那些大网站做了 学习用的 只用到前端 无后端内容 想改成后端的 思路大概就是 后端切割图片 然后把图片传给前端 前端展示 前端完成拖拽后将坐标传回给后端 后端去判断与自己切割的地方是否一致 下面看图示
  • C++57个入门知识点_47 虚函数的多态性(成员函数中的虚函数具有多态性;构造和析构函数中,虚函数没有多态性;在构造析构函数中调用普通成员函数,该普通成员函数中有虚函数的间接调用,没有多态)

    本篇主要讨论两个问题 1 成员函数中 虚函数是否有多态性 答案为 有 2 构造和析构函数中 虚函数是否有多态性 答案为 无 1 成员函数中 虚函数是否有多态性 成员函数中的虚函数具有多态性 以下代码中 void test foo 普通成员函