C++反汇编——多态,面试题01

文章目录

  • 1.C++的三大特性
    • 1.1封装
    • 1.2继承
    • 1.3多态
      • 1.3.1 虚函数
      • 1.3.2 多态代码+反汇编分析。
        • 反汇编分析1——基类指针指向子类对象,构造过程。
        • 反汇编分析2——基类指针指向子类对象,调用虚函数getPrice()过程。
        • 反汇编分析3——基类对象,调用虚函数getPrice()过程。
        • 反汇编分析4——基类指针指向子类对象,析构过程。
        • 反汇编分析5——基类指针指向子类对象,析构过程,基类析构函数不是虚函数时。
      • 1.3.3 静态多态vs动态多态

1.C++的三大特性

1.1封装

将对象的属性和方法封装起来。为了模块化,便于使用者操作,同时可以隔离外部使用者对内部数据的干扰,提高了安全性。

类成员的三种属性:
private:本类使用。设置get和set方法,因为通过接口来访问和修改数据是可控的,相对安全。
protected:本类和子类使用。
public:公开的,都可以访问。

1.2继承

允许通过继承原有类的某些特性或全部特性而产生新的类,原有的类称为基类(父类),产生的类称为派生类(子类)。为了扩展和重用,减少重复代码。

1.3多态

发生在继承关系中,不同的对象,对于相同的方法有不同的操作逻辑。为了接口重用,提高代码的可复用性、可维护性和可扩充性。

多态的实现机制为虚函数。

1.3.1 虚函数

关键字:virtual

作用:允许在子类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和子类的同名函数。

最常见的用法:声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。

实现原理:虚表+虚表指针。
在这里插入图片描述
当类存在虚函数时,编译器会为类创建一个虚表,虚表是一个数组,数组的元素存放的是虚函数地址。同时为每个类对象添加一个隐藏数据成员,即虚表指针,它被定义在对象首地址处。
**【注意】**虚表只有一份,而有多少个对象,就有多少个虚表指针。

1.3.2 多态代码+反汇编分析。

1.定义了一个基类,图形类Shape,数据成员分别为价格price和面积area,两个虚成员函数分别为获取图形描述getDescription()和获取图形价格getPrice(),虚析构函数;
2.定义了一个子类,圆形类Circle,继承Shape,数据成员为半径radius,重写父类方法getDescription()和getPrice();
3.定义了一个子类,矩形类Rectangle,继承Shape,数据成员分别为长度length和宽度width,重写父类方法getDescription()和getPrice();
4.main()里,基类指针s1指向Circle类对象,基类指针s2指向Rectangle类对象,基类对象s3。

// ConsoleApplication5.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include<iostream>
#include<string>
using namespace std;class Shape 
{
protected:double price;double area;public:Shape() :price(100),area(0) {}virtual ~Shape() { printf("%s\n", "Delete shape"); }virtual void getDescription() { printf("%s\n", "Base shape");}virtual void getPrice() { printf("%s%f\n", "Shape price ",price); }
};class Circle : public Shape 
{
private:double radius; public:Circle(double r) : radius(r) { area = 3.14 * radius * radius; price = 100 + area * 6; }~Circle() { printf("%s%f\n", "Delete circle with radius ",radius); }void getDescription() { printf("%s%f\n", "Circle with radius ",radius);}void getPrice(){ printf("%s%f%s%f\n", "Circle with area ", area," price ",price); }
};class Rectangle : public Shape {
private:double length;double width;  public:Rectangle(double l, double w) : length(l), width(w) { area = length * width; price = 100 + area * 6; }~Rectangle() { printf("%s%f%s%f\n", "Delete rectangle with length ", length," and width ",width); }void getDescription() { printf("%s%f%s%f\n","Rectangle with length ", length, " and width ", width);}void getPrice() { printf("%s%f%s%f\n", "Rectangle with area ", area, " price ", price); }
};int main() {Shape* s1 = new Circle(5.0);Shape* s2 = new Rectangle(4.0, 6.0);s1->getPrice();s2->getPrice();Shape s3;s3.getPrice();s3.getDescription();delete s1;delete s2;_CrtDumpMemoryLeaks();return 0;
}

程序执行结果,如下图。
在这里插入图片描述

反汇编分析1——基类指针指向子类对象,构造过程。

1.调用子类构造函数(Rectangle),如下图。
在这里插入图片描述

2.调用父类构造函数(Shape),如下图。
看寄存器eax,对象s2地址0x014E5AB8;
虚表指针0x00DC9E10;
length地址eax+18h,0x0014E5AD0;
width地址eax+20h,0x0014E5AD8;
在这里插入图片描述
area=length * width,area地址eax+10h,0x0014E5AC8。
price=100 + area * 6,price地址eax+8h,0x0014E5AC0,如下图。
请添加图片描述
基类数据成员声明顺序price、area。
子类数据成员声明顺序length、width,如下图。
在这里插入图片描述

反汇编分析2——基类指针指向子类对象,调用虚函数getPrice()过程。

1.取对象s2地址,存放进eax,0x014E5AB8。
2.取虚表指针,存放进edx,0x00DC9E10。
3.取虚函数getPrice()地址,0x00DC14D3,并调用,如下图。
在这里插入图片描述

反汇编分析3——基类对象,调用虚函数getPrice()过程。

基类对象调用自身虚函数时,没有构成多态性,所以没必要查表访问,编译器使用了直接调用方式,如下图。

基类对象s3地址0x0118FE90。
虚表指针0x00DC9F64。
虚析构函数地址0x00DC14BF。
虚函数getDescription()地址0x00DC10CD。
虚函数getPrice()地址0x00DC14CE。

虚函数声明顺序:析构函数、getDescription()、getPrice()。
在这里插入图片描述

反汇编分析4——基类指针指向子类对象,析构过程。

在这里插入图片描述
在这里插入图片描述
1.调用子类析构函数(Circle),如下图。
在这里插入图片描述
2.释放子类资源后,调用父类析构函数(Shape),如下图。
在这里插入图片描述

反汇编分析5——基类指针指向子类对象,析构过程,基类析构函数不是虚函数时。

只调用基类析构函数,如下图。
**【注意】**由于子类析构函数不会被调用,子类资源没有正确释放,造成内存泄漏。
在这里插入图片描述
在这里插入图片描述

1.3.3 静态多态vs动态多态

1.静态多态在编译期完成,由模板实现;而动态多态在运行期完成,由继承、虚函数实现。
2.静态多态中接口是隐式的,以有效表达式为中心;而动态多态中接口是显式的,以函数签名为中心。
3.**【注意】**虚函数表在编译的时候就确定了,而类对象的虚函数指针是在运行阶段确定的,这是实现多态的关键!

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

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

相关文章

WebRTC实现多人通话-Mesh架构【保姆级源码教程】

一、Mesh架构 WebRTC&#xff08;Web Real-Time Communications&#xff09;中的Mesh架构是一种将多个终端之间两两进行连接&#xff0c;形成网状结构的通信模式。以下是关于WebRTC的Mesh架构的详细解释&#xff1a; 基本概念&#xff1a;在Mesh架构中&#xff0c;每个参与者…

html实现网页插入音频

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要介绍html中 如何插入音乐和视频 视频插入 标签:<video></video> 兼容格式:mp4,因为别的浏览器都有不兼容的格式&#xff0c;唯一对mp4全都兼容。所以尽量使用mp4格式。 属性: 属性属性值…

学生管理系统初级

根据题目要求生成大纲 总结: 1.在书写时&#xff0c;考虑到了书写时id可是是abc... 类型是String&#xff0c;但在根据id获取集合中元素时 list.get() &#xff0c;get&#xff08;&#xff09;里面是int类型。 2.在书写还有一点功能并不完全&#xff0c; 2.1查找时是打印所有…

Open CASCADE学习|三重正交标架法则

三重正交标架&#xff08;Trihedron&#xff09; 定义:三重正交标架是在三维空间中定义的一个坐标系&#xff0c;由三个互相垂直的向量构成。这些向量分别是&#xff1a; 切线向量&#xff08;Tangent Vector&#xff09; - 表示曲线在某一特定点处的切线方向。 主法线向量&…

代码随想录算法训练营第十三天:树的认知(补五一)

代码随想录算法训练营第十三天&#xff1a;树的认知&#xff08;补五一&#xff09; ‍ 二叉树的递归遍历 #算法公开课 《代码随想录》算法视频公开课 ****(opens new window)****​ &#xff1a;​每次写递归都要靠直觉&#xff1f; 这次带你学透二叉树的递归遍历&#xf…

cmake进阶:文件操作之写文件

一. 简介 cmake 提供了 file() 命令可对文件进行一系列操作&#xff0c;譬如读写文件、删除文件、文件重命名、拷贝文件、创建目录等等。 接下来 学习这个功能强大的 file() 命令。 本文学习 CMakeLists.txt语法中写文件操作。 二. cmake进阶&#xff1a;文件操作之写文件…

基于家政小程序的个性化家政服务研究

基于家政小程序的个性化家政服务研究&#xff0c;是近年来随着移动互联网技术的快速发展和人们生活品质的提高而兴起的一个热门话题。以下是对该领域的研究探讨&#xff1a; 一、引言 随着现代生活节奏的加快&#xff0c;家政服务已成为越来越多家庭不可或缺的一部分。然而&a…

​​【收录 Hello 算法】3.3 数字编码

目录 3.3 数字编码 3.3.1 原码、反码和补码 3.3.2 浮点数编码 3.3 数字编码 Tip 在本书中&#xff0c;标题带有 * 符号的是选读章节。如果你时间有限或感到理解困难&#xff0c;可以先跳过&#xff0c;等学完必读章节后再单独攻克。 3.3.1 原码、反码和补码 在…

BetterMouse for Mac激活版:鼠标增强软件

BetterMouse for Mac是一款鼠标增强软件&#xff0c;旨在取代笨重的、侵入性的和耗费资源的鼠标驱动程序&#xff0c;如罗技选项。它功能丰富&#xff0c;重量轻&#xff0c;效率优化&#xff0c;而且完全隐私安全&#xff0c;试图满足你在MacOS上使用第三方鼠标的所有需求。 B…

Dell EMC Storage Unity: Remove/Install Memory Module

SP A 一个内存故障 点击system view -> Enclosures->Top查看 再次查看Alert&#xff0c; 确认内存出现问题 进入Service &#xff0c; 将SP A置为service状态 移出SP A &#xff0c;进行内存更换 更换完内存后&#xff0c;将SP A插入设备&#xff0c;并进行线缆连接 进入…

视频素材哪个软件好用?8个短视频素材高清无水印

在今日这个视觉表现至关重要的时代&#xff0c;获取合适的视频素材成为制作任何类型视频内容的基石。从企业宣传片到社交媒体短视频&#xff0c;高质量的视频素材能够显著提升内容的吸引力和专业度。这里列出了一些全球顶尖的视频素材平台&#xff0c;每一个都能为您的视频项目…

微信小程序miniprogram_npm目录主包太大如何处理

在使用TDesign开发小程序&#xff0c;miniprogram_npm目录下很多组件&#xff0c;感觉很多组件我都没引用&#xff0c;为什么都在主包来&#xff0c;导致主包很大。如何优化&#xff1f; 在使用npm构建后生成的miniprogram_npm目录里&#xff0c;有所有TDesign组件。但是有很…