C++多态练习题

news2025/1/20 19:10:28

文章目录

  • 1.虚函数的调用过程
  • 2.虚函数例题
    • 例题一
    • 例题二
    • 例题三
    • 例题四
    • 例题四

1.虚函数的调用过程

从汇编上面来看:

在这里插入图片描述
[]代表指针解引用操作

1.op指向test对象的首地址(存放vptr),并存放在eax里面;

2.将eax所指之物(虚表的首地址)给edx

3.op所指之物给ecx(test的this指针执向了vptr),并将vptr的地址给了ecx

4.[edx+8],edx代表虚表里面的首地址add函数,+8就是指针偏移8字节,此时指向的print函数,并将print函数给eax

5.call:返回eax,此时eax里面是print函数的地址

2.虚函数例题

例题一

class Object
{
private:
	int value;
public:
	Object(int x=0):value(x){}
	void print()
	{
		cout << "Object::print" << endl;
		add(1);
	}
	virtual void add(int x)
	{
		cout << "Object::add" << x << endl;
	}
};

class Base:public Object
{
private:
	int num;
public:
	Base(int x=0):Object(x+10),num(x){}
	void show()
	{
		cout << "Base::show" << endl;
		print();
	}
	virtual void add(int x)
	{
		cout << "Base::add:" << endl;
	}
};
int main()
{
	Base base;
	base.show();
	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

例题二

class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x)
	{
		cout << "Create Object:" << endl;
		add(12);
	}
	~Object()
	{
		cout << "Destory Object:" << endl;
	}
	virtual void add(int x)
	{
		cout << "Object::add" << endl;
	}
	
};

class Base :public Object
{
private:
	int num;
public:
	Base(int x = 0) :Object(x + 10), num(x) 
	{
		cout << "Base Object:" << endl;
		add(1);
	}
	~Base()
	{
		cout << "Destory base:" << endl;
		add(2);
	}
	virtual void add(int x)
	{
		cout << "Base::add:" << endl;
	}
};
int main()
{
	Base base;
	return 0;
}

在这里插入图片描述

  • 构造函数是设置虚表指针
    在没有调用构造函数,对象未被构建时,对象里面的属性都为随机值
  • 析构函数是重置虚表指针
  • 构造函数和析构函数采用静态联编,不进行查表

例题三

class Object
{
public:
	virtual void func(int a = 10)
	{
		cout << "Object::func:a" <<a<< endl;
	}
};
class Base :public Object
{
private:
	virtual void func(int b = 20)
	{
		cout << "Base ::fun:b" << b << endl;
	}
};
int main()
{
	Base base;
	Object* op = &base;
	op->func();
	return 0;
}

在这里插入图片描述
此题目将动态联编和静态联编发挥到了极致
在这里插入图片描述

例题四

class Object
{
private:
	int value = 10;
public:
	Object(int x = 10)
	{
		cout << "create object" << endl;
	}
	void func(int a=10)
	{
		cout << "func::"<<a << value << endl;
	}
	virtual void print()const
	{
		cout << "print" << endl;
	}
};
int main()
{
	Object obj(10);
	Object* op = (Object*)malloc(sizeof(Object));
	op->print();
	op->func();
	return 0;
}

在这里插入图片描述
引发了异常,原因是将对象赋值给空间,系统只负责将数据赋值,不进行虚函数指针的赋值,也就是说虚表指针仍然是随机值,解决方法一:去掉虚函数。
解决办法二:定位new

int main()
{
	Object obj(10);
	Object* op = (Object*)malloc(sizeof(Object));
	*op = obj;
	new(op)Object(obj); //通过拷贝构造对op所指针的空间构造对象
	op->print();
	op->func();
	return 0;
}

在这里插入图片描述

例题四

class Object
{
private:
	int value;
public:
	Object(int x = 0) :value(x)
	{
		cout << "Create Object:" << endl;
		add(12);
	}
	~Object()
	{
		cout << "Destory Object:" << endl;
	}
	virtual void add(int x)
	{
		cout << "Object::add" << endl;
	}

};

class Base :public Object
{
private:
	int num;
public:
	Base(int x = 0) :Object(x + 10), num(x)
	{
		cout << "Base Object:" << endl;
		add(1);
	}
	~Base()
	{
		cout << "Destory base:" << endl;
		add(2);
	}
	virtual void add(int x)
	{
		cout << "Base::add:" << endl;
	}
};
int main()
{
	Object* op = new Base(10);
	op->add(10);
	delete op;
	return 0;
}

在这里插入图片描述
此时我们发现base并没有被析构掉,造成内存泄露,解决办法是将Object的析构函数设置为虚函数
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

使用不同的梯度下降法优化算法

本篇将使用以下几个梯度下降算法进行对比&#xff1a; 不使用任何的优化算法&#xff08;即整批数据集作为一次迭代更新梯度&#xff0c;也叫batch梯度下降&#xff0c;BGD&#xff09; mini-batch梯度下降法&#xff08;Mini-batchGD&#xff09; 使用具有动量的梯度下降算法&…

无标签背景图(负样本)的拼图代码

训练目标检测模型有个很令人头疼的问题&#xff0c;就是有些特征与要训练的特征较为相似的背景区域也被误检出来&#xff08;作为本应不该检测出来的负样本却被误检出为正样本的FP&#xff09;。 根据这一问题的解决办法&#xff0c;除了可以对正样本特征较为模糊或者有歧义的样…

Intel SGX学习笔记(2):用数组向Enclave传递5个数实现自增操作

写在前面 1、实现一个简单的Intel SGX的应用&#xff1a;非安全区定义初始化一个数组&#xff0c;数组里面存储5个数&#xff0c;然后向安全区&#xff08;enclave&#xff09;传入&#xff0c;在安全区中进行加减乘除&#xff0c;然后返回。 2、Intel SGX开发初学整体思路&a…

代码随想录算法训练营day39 | 62.不同路径,63. 不同路径 II

代码随想录算法训练营day39 | 62.不同路径&#xff0c;63. 不同路径 II 62.不同路径解法一&#xff1a;动态规划解法二&#xff1a;深度搜索&#xff08;明天补充&#xff09;解法三&#xff1a;数论&#xff08;明天补充&#xff09; 63. 不同路径 II解法一&#xff1a;动态规…

RuoYi-Vue下载与运行

一、源码下载 若依官网&#xff1a;RuoYi 若依官方网站 鼠标放到"源码地址"上&#xff0c;点击"RuoYi-Vue 前端分离版"。 跳转至Gitee页面&#xff0c;点击"克隆/下载"&#xff0c;复制HTTPS链接即可。 源码地址为&#xff1a;https://gitee.…

左值引用、右值引用,std::move() 的汇编解释

1&#xff1a;左值引用 引用其实还是指针&#xff0c;但回避了指针这个名字。由编译器完成从地址中取值。以vs2019反汇编&#xff1a; 如图&#xff0c;指针和引用的汇编代码完全一样。但引用在高级语言层面更友好&#xff0c;对人脑。比如可以少写一个 * 号和 -> 。 &…

F280049C实现Simulink调制,以及多个PWM实例之间的同步

文章目录 前言基本概念调制发波载波同步问题 前言 最近作实验碰到了载波不同步的问题&#xff0c;以前也有碰到过这个问题&#xff0c;现在终于解决了&#xff0c;做个记录。 为了以示区分&#xff0c;实例指ePWMx&#xff0c;x1,2,3,4,5,6,7,8&#xff1b;通道指ePWMxA/B&am…

如何使用jmeter进行压测

目录 1.概述 2.测试计划、线程组、取样器 3.调试运行 4.请求默认值 5.流量录制 6.模拟时间间隔 7.压力测试 8.报表 1.概述 一款工具&#xff0c;功能往往是很多的&#xff0c;细枝末节的地方也很多&#xff0c;实际的测试工作中&#xff0c;绝大多数场景会用到的也就是…

看大老如何用Postman+Jmeter实现接口实例

一、接口基础 为什么要单独测试接口&#xff1f; 1. 程序是分开开发的&#xff0c;前端还没有开发&#xff0c;后端已经开发完了&#xff0c;可以提前进入测试 2. 接口直接返回的数据------越底层发现bug&#xff0c;修复成本是越低的 3. 接口测试能模拟功能测试不能测到的异常…

数十位高级测工联合讲解Selenium自动化测试框架工作原理

一、Selenium是什么&#xff1f;   用官网的一句话来讲&#xff1a;Selenium automates browsers. Thats it&#xff01;简单来讲&#xff0c;Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作浏览器一样。支持…

uvm寄存器模型

一、基础知识 前门访问与后门访问是两种寄存器的访问方式。 所谓前门访问, 指的是通过模拟cpu在总线上发出读指令, 进行读写操作。 在这个过程中, 仿真时间( $time函数得到的时间) 是一直往前走的。而后门访问是与前门访问相对的概念。 它并不通过总线进行读写操作, 而是…

2023/5/14周报

目录 摘要 论文阅读 1、标题和现存问题 2、准备知识 3、模型结构 4、实验准备 5、实验结果 深度学习 1、大气数据和水质数据 2、数据清洗 3、项目框架设定 总结 摘要 本周在论文阅读上&#xff0c;阅读了一篇时空图卷积网络:交通预测的深度学习框架的论文。文章的时…

oracle使用with as创建临时表

一、业务需求 在oracle项目的开发过程中&#xff0c;使用sql编写好对应的分析报表内容后&#xff0c;由于sql分析报表涉及到的一些线别丢失&#xff0c;导致呈现的报表分类统计时固定用醒目颜色标识的统计行数据显示错位&#xff1b;因此需要修复分析报表填充完整的线别。 二、…

LeetCode 62 不同路径

题目&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。问总共有多少条不同的路径&#…

云上高校导航 小程序 开发教程

Gitee仓库&#xff1a;云上高校导航 GitHub仓库&#xff1a;云上高校导航 “云上高校导航”是一套基于小程序云开发的校园导航类系统开发方案&#xff0c;该开发方案可供开发者进行二次开发&#xff0c;用于解决师生和访客的校园出行需求。 项目优势及创新&#xff1a; 使…

Flink 常用API(2)——转换算子+聚合算子

转换算子&#xff08;Transformation&#xff09; 映射&#xff08;map&#xff09; 用于将数据流中的数据进行转换&#xff0c;形成新的数据流 “一一映射”&#xff0c;消费一个元素就产出一个元素 参数&#xff1a;接口 MapFunction 的实现 方法&#xff1a;map 返回值…

C#串口通信从入门到精通(13)——多个串口发送数据

文章目录 前言1、多串口数据的发送2、源码前言 我们在开发串口通信程序时,有时候会需要连接不止一个串口,这时候该怎么写程序呢?本文就来介绍多个串口数据的发送 1、多串口数据的发送 我们在之前的专栏中介绍了串口数据的发送,当时有提到过,我们是通过创建一个SerialPo…

支付系统设计三:渠道网关设计06-业务处理

文章目录 前言一、业务服务工厂二、业务处理服务1. 业务处理服务2. 业务处理抽象服务3. 流量控制4. 报文提交4.1 获取交易的服务端通讯列表4.2 循环请求支付渠道4.2.1 报文组装4.2.2 报文发送4.2.2.1 协议处理器获取4.2.2.2 构建通讯客户端4.2.2.3 发送请求4.2.2.4 响应报文读取…

【rust】| 06——语言特性 | 所有权

系列文章目录 【rust】| 00——开发环境搭建 【rust】| 01——编译并运行第一个rust程序 【rust】| 02——语法基础 | 变量(不可变?)和常量 【rust】| 03——语法基础 | 数据类型 【rust】| 04——语法基础 | 函数 【rust】| 05——语法基础 | 流程控制 【rust】| 06——语言特…

论文/文章/课设 不会写 后端的实现方式?来试试这个吧!

起因 有朋友用了云开发&#xff0c;但是不太会写&#xff0c;老师也不太理解&#xff0c;就来询问我该怎么写&#xff08;不要苛责老师古板&#xff0c;他们确实不一定能够立刻接受新东西&#xff09; 用的不是云开发的也适用以下思路 思路 我们把后端开发类比成拧螺丝&…