C++类细节,反汇编,面试题02

文章目录

  • 2. 虚函数vs纯虚函数
  • 3. 重写vs重载vs隐藏
    • 3.1. 为什么C++可以重载?
  • 4. struct vs union
    • 4.1. 为什么要内存对齐?
  • 5. static作用
  • 6. 空类vs空结构体
    • 6.1. 八个默认函数:
    • 6.2. 为什么空类占用1字节
  • 7. const作用
    • 7.1 指针常量vs常量指针vs常量指针常量
  • 8. 接口vs抽象类
  • 9. 浅拷贝vs深拷贝
    • 9.1. 深拷贝应用场景
    • 9.2. 调用拷贝构造函数的三种情况
  • 10. 写时拷贝

2. 虚函数vs纯虚函数

  • virtual修饰的成员函数就是虚函数,它允许在子类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和子类的同名函数。引入虚函数是为了动态绑定。
  • 纯虚函数除了关键字virtual外,还要 =0, 它是在基类中声明但没有定义的虚函数,要求子类必须提供实现。引入纯虚函数是为了派生接口,即子类仅仅只是继承函数的接口。

3. 重写vs重载vs隐藏

  • 重写:发生继承关系中,子类重写父类的方法。
  • 重载:发生在同一个类中,函数名相同,但参数个数或类型不同。
  • 隐藏:子类函数屏蔽了与其同名的基类函数,有以下两种情况:
    1、参数不同,基类函数被隐藏 (而不是重载)
    2、参数相同,但基类函数没有virtual关键字,基类函数被隐藏 (而不是重写)

3.1. 为什么C++可以重载?

  • C++引入了命名空间,以及作用域,比如类作用域,命名空间作用域。
  • 函数在编译期间,链接符号的时候,会在符号后追加一些特殊标识,比如add函数,变成add@123。

4. struct vs union

  • 相同:都可以将不同类型的变量组合成一个整体。
  • 区别
    • struct 里的每个成员都有自己独立的内存空间;sizeof(struct) 是内存对齐后所有成员长度的总和。
    • union 里的所有成员共享同一内存空间;sizeof(union) 是内存对齐后最大的数据成员长度。

4.1. 为什么要内存对齐?

  • 确保代码在不同平台上的兼容性。
  • 提高内存访问的效率。
  • ps:在Visual Studio中,默认对齐值8,将它与结构体中最大的数据成员长度进行比较,取两者的较小值,设定为实际对齐值。

5. static作用

  • static修饰的成员变量就是类变量,是类的所有对象共有的。
  • static修饰的成员函数就是类方法,类方法不能访问对象变量只能访问类变量,可以由类名直接调用,也可以由对象调用。
  • static修饰的局部变量就是局部静态变量,在函数内可以访问到。
  • static修饰的全局变量就是全局静态变量,是当前文件内可以访问到。
  • ps:对象变量,是每个对象单独拥有的。
  • ps:const强调值不能被修改,而static强调内存只有一份拷贝。

6. 空类vs空结构体

  • 空类:默认private。
  • 空结构体:默认public。

6.1. 八个默认函数:

  • 构造函数 【A();】
  • 析构函数 【~A();】
  • 拷贝构造函数 【A (const A&);】
  • 重载赋值运算符 【A&operator = (const A&);】
  • 重载取址运算符 【A* operator& ();】
  • 重载取址运算符const 【const A* operator& () const;】
  • 移动构造函数(C++11) 【A(A&&);】
  • 重载移动赋值运算符(C++11)【A& operator = (const A&&);】

6.2. 为什么空类占用1字节

  • 因为如果对象完全不占用内存空间,空类就无法取得实例的地址,this指针失效,因此不能被实例化。而类的定义是由数据成员和成员函数组成的,在没有数据成员情况下,还可以有成员函数,因此仍然需要实例化。

7. const作用

  • 限定变量不可修改。
  • 限定成员函数不可修改数据成员(后置const)。
  • 成员函数的返回值类型是const,则返回值不是左值(前置const)。
  • 用const对函数的参数修饰,表面是输入参数,在函数内不可写。
  • const函数只能调用const函数,非const函数可以调用const函数。

7.1 指针常量vs常量指针vs常量指针常量

  • 指针常量,即指针本身是常量,所以指针的值(内存地址)不能改变,示例如下。
    int a = 10, b = 20;int* const p= &a;p = &b;  //错误,指针存放的内存地址不可变*p= 100; //正确,内存地址存放的内容可以改变
  • 常量指针,即指向常量的指针,不能通过指针修改指向的内容,示例如下。
    const int a = 10;int b = 20;const int* p = &a;p = &b; //正确, 指针存放的内存地址可变*p = 100; //错误,指针指向的内容不可变b = 100; //正确,可以通过原来的声明修改
  • 常量指针常量,即指向常量的指针本身也是常量,不能通过指针修改指向的值,指针的值不能改变,示例如下。
    const int a = 10;int b = 20;const int* const p = &a;p = &b; //错误, 指针存放的内存地址不可变*p = 100; //错误,指针指向的内容不可变

8. 接口vs抽象类

  • 抽象类:带有纯虚函数的类。
    抽象类作用:为了扩展和重用。
  • 接口:没有数据成员;成员函数都是公有的、都是纯虚函数,虚析构函数除外;是完全抽象的类。
    接口作用:只提供了一种规范,实现接口的类必须实现接口中的所有方法。
  • 相同:都不能实例化,但可以创建指针。
  • 代码如下。
// ConsoleApplication5.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include<iostream>
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() = 0; virtual void getPrice() = 0;
};//接口
class Draw
{
public://虚析构函数virtual ~Draw() { printf("%s\n", "Delete Draw"); }//纯虚函数:输出图形周长virtual void drawLen() = 0;  
};//具体类
class Circle : public Shape,public Draw
{
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); }void drawLen() { printf("%s%f\n", "Circle with len ", 2 * 3.14 * radius); }
};int main() {Circle c(5.0);Shape* s = &c; //基类(Shape)指针指向子类(Circle)对象s->getDescription();s->getPrice();Draw* d = &c;  //基类(Draw)指针指向子类(Circle)对象d->drawLen();_CrtDumpMemoryLeaks();return 0;
}
  • 程序执行结果,如下图。

在这里插入图片描述

9. 浅拷贝vs深拷贝

  • 浅拷贝只是将指针拷贝,指向同一块内存。
  • 深拷贝是直接将内存拷贝一份。

9.1. 深拷贝应用场景

  • 【注意】 当类成员变量是指针,为它动态分配内存时,有以下两种bug情况:
    1、若使用默认的重载赋值运算符进行浅拷贝,即a和b指向同一内存,但b曾指向的内存不会被删除,造成内存泄漏;若一方离开了它的生存空间,使用析构函数释放资源,另一方会变成悬空指针,导致未定义行为;同时当另一方调用析构函数时,会因重复释放同一堆空间而触发中断。
    2、若使用默认的拷贝构造函数进行浅拷贝,会重复释放同一内存。
    所以,为避免这两种bug情况,需要进行深拷贝。
  • 修改一个对象不会影响到另一个对象时,进行深拷贝以确保每个对象都有自己独立的数据副本。

9.2. 调用拷贝构造函数的三种情况

  • 用一个对象去初始化另一个对象时。
  • 当函数的参数是对象时,形参是实参的副本,即拷贝构造了一个新对象。
    • vs 但当函数的参数是对象引用或对象指针时,是直接传递对象this指针,无需拷贝。
  • 当函数的返回值是对象引用时,由于临时对象离开了函数就会消失,所以要对临时对象进行拷贝,构造一个新对象。【注意】 当临时对象出了函数作用域后,存放它数据的那块内存随时会被占用,写入新数据,所以在拷贝构造过程中 【存在安全隐患】,即它可能拷贝别的内容,代码和反汇编如下。
    • vs 但当函数的返回值是对象指针时,由于指针指向临时对象,所以临时对象还没消失,并且也无需进行拷贝。
    • vs 【注意】 但当函数的返回值是对象时,不一定会调用拷贝构造函数,因为C++编译器通常会进行返回值优化,即它直接传递保存返回值的对象this指针,然后在函数内直接构造,由于这个对象是在函数外定义的,所以不会受函数作用域的影响。
#include <iostream>
using namespace std;class A {
private:int data;
public:A(int i) { data = i; } 	A(const A& a){data = a.data;cout << "拷贝构造函数执行完毕" << endl;}};A& getA() {A a(3);return a;
}int main() {A d1 = getA();      		    			return 0;
}

eax保存返回的临时对象地址,如下图。
在这里插入图片描述
由于临时对象的内存空间被占用了,写入了新数据,所以新对象拷贝了错误的内容,如下图。
在这里插入图片描述

10. 写时拷贝

  • 在使用系统重要的dll或者系统一些函数的时候,系统为了节省空间和提高性能,会直接映射一份共享地址,但当我们对其进行修改时,会触发写时拷贝,会拷贝一份给我们进程内使用,防止我们去修改共享的地址,影响整个系统。

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

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

相关文章

【SRC-CPP-OpenCV】给图片更换背景色

文章目录 Part.I IntroductionPart.II Main_bodyChap.I 源码简析Chap.II 效果展示 Part.III 源码Reference Part.I Introduction 本文将介绍如何用 OpenCV 更换图片的背景色&#xff08;附有完整代码&#xff09;。 Part.II Main_body Chap.I 源码简析 配置部分&#xff1a…

1-3ARM_GD32点亮LED灯

简介&#xff1a; 最多可支持 112 个通用 I/O 引脚(GPIO)&#xff0c;分别为 PA0 ~ PA15&#xff0c;PB0 ~ PB15&#xff0c;PC0 ~ PC15&#xff0c;PD0 ~ PD15&#xff0c;PE0 ~ PE15&#xff0c;PF0 ~ PF15 和 PG0 ~ PG15&#xff0c;各片上设备用其来实现逻辑输入/输出功能。…

【论文精读】| KBS2023-TMBL-多模态情感分析系列文章解读

TMBL: Transformer-based multimodal binding learning model for multimodal sentiment analysis 一. KBS2023-TMBL-用于多模态情感分析的极向量和强度向量混合器模型1 Abstract1.1 Motivation1.2 Method1.3 Results 2. Related Work2.1 情感分析2.1 基于transformer的2.1 模态…

LeetCode/NowCoder-链表经典算法OJ练习2

最好的&#xff0c;不一定是最合适的&#xff1b;最合适的&#xff0c;才是真正最好的。&#x1f493;&#x1f493;&#x1f493; 目录 说在前面 题目一&#xff1a;分割链表 题目二&#xff1a;环形链表的约瑟夫问题 SUMUP结尾 说在前面 dear朋友们大家好&#xff01;&…

(done) 什么是马尔可夫链?Markov Chain

参考视频&#xff1a;https://www.bilibili.com/video/BV1ko4y1P7Zv/?spm_id_from333.337.search-card.all.click&vd_source7a1a0bc74158c6993c7355c5490fc600 如下图所示&#xff0c;马尔可夫链条实际上就是 “状态机”&#xff0c;只不过状态机里不同状态之间的边上是 “…

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈)

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你…

实战WinRAR捆绑图片和恶意程序并自动上线Cobalt Strike(cs钓鱼日记)

钓鱼 - WinRAR捆绑图片和恶意程序并自动上线Cobalt Strike 环境准备 工具&#xff1a;Cobalt Strike、Winrar压缩工具、一张JPG图片 虚拟机IP&#xff1a; 【攻击机】Kali&#xff1a;192.168.232.128 【靶机】win7&#xff1a;192.168.232.144 情景&#xff1a;在钓鱼事…

老黄终于不穿皮衣了,分享一个AI换装AI试衣软件!

用AI实现在线试衣&#xff0c;或者在线换装&#xff0c;这不是一个新概念&#xff0c;肯定有人这么想过&#xff0c;但并不是所有人能都能轻松做到啊&#xff01; 今天就来分享一个人人都可以实现的方法&#xff0c;而且是那种傻瓜式的不用付钱的那种&#xff0c;甚至可以把软件…

大数据在IT行业的应用与发展趋势及IT行业的现状与未来

大数据在IT行业中的应用、发展趋势及IT行业的现状与未来 一、引言 随着科技的飞速发展&#xff0c;大数据已经成为IT行业的重要驱动力。从数据收集、存储、处理到分析&#xff0c;大数据技术为各行各业带来了深远的影响。本文将详细探讨大数据在IT行业中的应用、发展趋势&#…

详解依赖注入的三种方法以及遇到问题的解决

各位大佬光临寒舍&#xff0c;希望各位能赏脸给个三连&#xff0c;谢谢各位大佬了&#xff01;&#xff01;&#xff01; 目录 1.三种依赖注入的方法 1.属性注入 优点 缺点 2.构造方法注入 优点 缺点 3.Setter注入 优点 缺点 4.小结 2.依赖注入常见问题的解决 1…

linux Nginx安装与启动

一、先到官网下载Nginx 官网地址&#xff1a; http://nginx.org/en/download.html 我下载的是nginx-1.20.2 二、下载好的文件上传到服务器&#xff0c;然后解压 1、上传到指定的服务器地址&#xff0c;我这里是公司服务器&#xff0c;目录都是定义好的&#xff0c;自己玩建…

本来还挺喜欢……

前阵子买了个天空星开发板&#xff0c;到手之后发觉不对劲。 之前我们玩玩开发板都是用的面包板的&#xff0c;就算是ESP那种比较宽的板子用两个面包板拼一下也勉强可以用。 但是天空星它的引脚是分为两组&#xff0c;每组有两排&#xff0c;如果我们还是直接使用面包板的话&a…

单页源码加密屋zip文件加密API源码

简介&#xff1a; 单页源码加密屋zip文件加密API源码 api源码里面的参数已改好&#xff0c;往服务器或主机一丢就行&#xff0c;出现不能加密了就是加密次数达到上限了&#xff0c;告诉我在到后台修改加密次数 点击下载

【文献阅读】企业ESG表现与创新——来自A股上市公司的证据

企业ESG表现与创新——来自A股上市公司的证据 1.引言 第一段——背景介绍 可持续发展 碳达峰、碳中和 ESG既是从微观层面解决全球性社会问题的必要&#xff0c;也是实现我国经济转型、促进高质量发展的有效手段。 2017.12证监会&#xff1a;重点排污企业的环境披露 2021.6证监…

【ARM Cortex-M 系列 2.1 -- Cortex-M7 Debug system registers】

请阅读【嵌入式开发学习必备专栏】 文章目录 Debug system registers中断控制状态寄存器&#xff08;ICSR&#xff09;Debug Halting Control and Status Register, DHCSR Debug 寄存器DCRSR与DCRDRCPU 寄存器读操作CPU 寄存器写操作CPU 寄存器选择CPU 寄存器读写示例 调试故障…

第十五篇:全面防护:构建不容侵犯的数据库安全策略与实战指南

全面防护&#xff1a;构建不容侵犯的数据库安全策略与实战指南 1. 引言&#xff1a;数据库安全的现代战略 1.1 简介&#xff1a;数据库安全在当今的数字化时代中的重要性 在数字化的浪潮中&#xff0c;数据已成为企业乃至国家的核心资产&#xff0c;其价值不亚于实体世界的黄…

第五百零三回

文章目录 1. 概念介绍2. 使用方法2.1 普通路由2.2 命名路由 3. 示例代码4. 内容总结 我们在上一章回中介绍了"使用get显示Dialog"相关的内容&#xff0c;本章回中将介绍使用get进行路由管理.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

RAG应用中的路由模式

依据的用户查询意图在 RAG 应用程序使用“路由控制模式”可以帮助我们创建更强大的 RAG 应用程序。我们通常希望用户能够访问的数据可以来自各种来源,如报告、文档、图片、数据库和第三方系统。 对于基于业务的 RAG 应用程序,我们可能还希望用户能够与其它业务系统进行交互,…

大模型微调方法汇总

微调方法 Freeze方法P-tuning方法 prefix-tuningPrompt TuningP-tuning v1P-tuning v2Lora方法 重要相关参数LoRA 的优势Qlora方法 相关参数微调经验 模型选择模型大小选择数据处理微调方案英文模型需要做词表扩充吗&#xff1f;如何避免灾难遗忘大模型的幻觉问题微调后的输出…

戴尔数据泄露影响近五千万用户,数据保护应该得到重视

据BleepingComputer报道&#xff0c;电脑制造商戴尔因网站漏洞遭黑客入侵&#xff0c;约4900万用户信息疑遭泄露。根据黑客发布的销售帖子&#xff0c;泄露数据最多的前五个国家分别是美国、中国、印度、澳大利亚和加拿大。 据BleepingComputer报道&#xff0c;电脑制造商戴尔因…