第二十二篇,C++面经之问答(一)

2023-05-16

目录

一、传引用有没有拷贝

二、引用和指针的区别

三、构造/析构函数中可不可以调用虚函数

四、怎样区分继承和组合

五、多态的实现原理、虚表虚指针

六、用过哪些设计模式

6.1状态模式

6.2享元模式

6.3单例模式

6.4工厂模式

6.5观察者

七、观察者模式中有哪些接口

八、生产消费机制的实现

九、生产者速度高于消费者速度怎么办

十、单例的懒汉式、饿汉式有什么区别


面试参加了不少,问答也积累了足够多,基础的、进阶的、学院派的、实践派的、奇葩的,都见识到了,有些也是让人哭笑不得。

后来养成了面完即整理的习惯,不直接照搬网上科班式严谨的论述,因为大部分人实际面试时做不到完整又流畅的表达,我就结合自己的理解和面试的临场发挥,对主要的或有特点的问答做下记录,并分享出来希望能帮到有需要的小伙伴。

为了避免单篇篇幅过长,我会分拆成几个,每篇的问答个数尽量控制在10个左右并控制篇幅,主题集中在C++、Qt,并持续更新,有错误的地方欢迎指正,别喷就好。

一、传引用有没有拷贝

没有。

上来就放一个让我心慌的问题,印象中引用就是为了解决拷贝问题的,而且上网查了之后确实也没有见到有讨论传引用的拷贝问题的,但又感觉直接回答没有好像虚虚的,也许我才疏学浅,还有别的内涵在里面吗?

二、引用和指针的区别

答案先TODO一下。

先说说这种面试官的心理,问这种看似基础实则刁钻的问题,居心何在呢,凸显自己或者PUA候选人?只能说有点儿太八股了。

三、构造/析构函数中可不可以调用虚函数

可以调用,语法上没问题,但起不到虚函数运行时多态调用的作用,不建议使用,容易造成理解上的混淆。

构造过程是先基类后子类,析构过程是先子类后基类,都是从基类指针指向子类实体对象来理解。

在构造函数中调用虚函数,因为构造函数执行完后对象才算构造完,才会生成虚函数表和虚指针,因此在构造过程中调用虚函数无法触发多态机制,只能按普通函数调用,调用的是类本地的函数。

在析构函数中调用虚函数,由于子类先于基类析构,因此在基类的析构函数中已无法多态调用至子类的虚函数,所以也只能按普通函数调用,调用的是类本地的函数。

四、怎样区分继承和组合

通常来讲,继承体现的是is-a的关系,即子类是基类的一种,如苹果树是一种树,那么苹果树继承自树;组合体现的是has-a的关系,即被组合对象是组合对象中的一部分,如树根、树叶都是树的一部分,那么树根、树叶和树是组合关系。

继承和组合都是代码复用的方式,在继承中基类的内部细节对子类可见,破坏了基类的封装性,且子类基类间耦合度高;组合关系中对象之间的内部细节互相不可见,封装性好,耦合度低,但整体对象中包含很多局部对象。

除非两个类之间是is-a的关系,否则尽量使用组合。

五、多态的实现原理、虚表虚指针

这是经典问题,也是C++程序员的立身之本,请务必掌握。

封装、继承、多态是OOP的三大基本特征。

多态以虚函数表和虚指针为基础实现。

在有虚函数的继承关系中,每个对象拥有一个虚指针,指向其虚函数表,在用基类指针或引用进行函数调用时,在虚函数表中找到实际对象中的函数地址。

六、用过哪些设计模式

6.1状态模式

项目中有报警功能,分为一级报警、二级报警、三级报警、无报警,这几种报警状态之间互有跳转,非常适合套用状态模式;而且先前的编码是冗长的if-else,这就更加适合状态模式的设计初衷了,于是对报警模块进行了重构。

重构完成后模块化程度、代码整洁行、可读性都大大提高,而且使用方便,印象中仅对外暴露一个调用接口即可,推广起来非常方便。

不过也有不足,就是状态模式的通病:类的数量很多。

6.2享元模式

开发的软件主要是面向大量硬件设备的监控,比如某种设备有100个,常规的做法就是创建100个界面实例,不过我的应用场景有一点儿特殊的是,这么多设备同时最多只看一个,也就是说不需要那么多设备界面同时显示着,这就有了升级改造的下手之地。

研究了一下决定采用享元模式进行改造,即仅创建一个该种设备的监控界面实例,利用后台数据对象中本就存在的唯一性标记,比如编号、IP地址等,在界面切换时根据标记进行数据的加载与切换显示,在用户无感的情况下即大大减少了界面实例的数量,降低了内存消耗。

此次重构也被领导作为样板推广。

6.3单例模式

我们当时的架构设计中,业务执行单元有多个,往上增加了一层业务管理类以方便集中管理,这个业务管理类做成了单例,记得是用的懒汉式。

软件初始化、业务调度、配置文件读写、设备监控、报警监控,等等,多个口子都涉及到顶层业务管理,而这种管理显然只能有一个出口,不能政出多门,所以设计成单例。

单例的重点:构造函数定义成私有的、instance和GetInstance()定义成static的、注意多线程竞争问题、懒汉饿汉的区别。

6.4工厂模式

工厂模式是结合着上面说的享元模式用的,当时的设备情况比较复杂,不是单纯的几类毫不搭边的设备,其中有那么几种,从软件角度来看是大同小异的,所以就抽象了一层基类、派生出几个子类,在享元模式生成界面实体的过程中,对这几种设备加了一层工厂模式,简化了外部调用时的复杂度,代码逻辑整体更有层次感。

6.5观察者

稍微上点儿规模的软件一般都会用到观察者模式或者更复杂的生产消费模式,不过说实在的,在我们的项目里这块代码不是我实际写的,但我看过很多遍,调bug的时候打断点也一行一行走过很多遍,可以说是门清。

我们的应用首先进入生产消费模式,从网络上接收数据,搜帧、解帧后发出通知,相当于生产,之后消费线程取走数据做进一步解析;

然后是观察者模式,消费线程解析完后,分发给界面显示、数据存储、业务计算等模块实现各自的需求。

七、观察者模式中有哪些接口

观察者分为发布者Publisher和订阅者Subscriber,对它们要设计抽象基类以对统一接口做出约束,并方便注册时对象的多态传递。

发布者中包含注册接口register()用来注册订阅者、注销接口detach()用来注销订阅者、通知接口notify()用来通知订阅者更新消息;

订阅者中包含更新接口update(),在发布者的通知接口中被调用,以更新消息。

八、生产消费机制的实现

类似观察者模式,但生产者消费者之间解除直接耦合,通过数据缓冲区及通知机制进行数据通信,生产者往数据队列加入数据,消费者从数据队列中取出数据做处理。

数据缓冲区为空时消费者线程cv处于wait状态并检测空状态标记,生产者线程可以往数据缓冲区中加入数据,数据加入完成后生产者通知消费者到缓冲区取数据;若缓冲区满,生产者wait并检测满状态标记以暂停加入,待消费者线程消费使得缓冲区不满并notify之后继续加入数据。

设置数据缓冲区的意义:解耦观察者模式、解决并发问题、解决生产消费步调不一致的问题。

九、生产者速度高于消费者速度怎么办

这个问题事后回想让人想骂街了,不知道是我没表达清楚还是面试官糊涂,问题八实际已经回答了这个问题,他可能理解成我在讲观察者了,把我整的很懵,绞尽脑汁我也不知道发生了什么,于是颤颤巍巍地答了个“限制生产的速度或者数量”,结果被人家鄙视一顿。

事后就上网查吧,说的都是设置缓冲区啊,所以我已经答过了啊怎么还要问,总之这家自以为是的公司让人感觉很奇葩,后面还有奇葩的问题。

十、单例的懒汉式、饿汉式有什么区别

所谓懒,即用到时才动作,即在用到该单例对象的地方才创建单例对象,写法一般即是在GetInstance()方法中创建,可能会引发线程同步问题,但也能节约程序初始化的耗时;

所谓饿,即上来就要吃就要创建,在main()函数执行前即执行new操作,后续GetInstance()方法直接返回该单例对象即可,避免了线程间竞争创建的问题,但增加初始化耗时。

这里增加一个对单例static的讲解,主要是为了通过类名访问:

(102条消息) 单例模式中instance为什么一定要是static的_naerna的博客-CSDN博客

十一、单例与全局变量

全局变量虽然也能提供单例模式实现的全局访问功能,但它保证不了类实例的唯一性;

而且全局变量无论被用到与否都会被创建,单例的懒汉式就没有这个问题,尤其在资源是敏感点时这个问题更加明显。

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

第二十二篇,C++面经之问答(一) 的相关文章

  • 数据结构:线性结构(C语言)

    文章目录 线性结构线性表什么是线性表线性表的抽象类型描述线性表的实现 广义表广义表定义多重链表 堆栈什么是堆栈堆栈的抽象数据类型描述堆栈的顺序存储实现堆栈的链式存储实现堆栈的应用 队列什么是队列队列的抽象数据类型描述队列的顺序存储实现队列的
  • 树(C语言)

    文章目录 树树的定义树的一些基本术语树的表示 树 树的定义 树 xff08 Tree xff09 xff1a n n 0
  • 堆(C语言)

    文章目录 堆 heap 什么是堆最小堆的操作操作集的实现 C语言 堆 heap 什么是堆 定义 堆 heap 是计算机科学中一类特殊的数据结构的统称 堆通常是一个可以被看做一棵树的数组对象 性质 结构性 xff1a 用数组表示的完全二叉树
  • VS2017中fopen等函数报错解决方法

    文章目录 VS2017中fopen 函数报错解决方法问题解决方法 VS2017中fopen 函数报错解决方法 问题 用VS2017写C语言代码的时候 xff0c 代码中使用了fopen 函数 xff0c 调试之后报错如下 xff1a err
  • 定位,浮动,BFC

    文章目录 1 xff0c 定位1 margin 与 padding 区别 xff1a 2 定位 xff1a 2 xff0c 元素分类 xff0c 浮动 xff0c BFC1 1 常见块级元素 xff1a 1 2 常见行内元素 xff1a 1
  • 表排序

    文章目录 表排序 表排序 思想 当待排数组中的元素不是简简单单的整数 xff0c 而是复杂的结构体 xff0c 那么移动元素所花费的时间就不能忽略不计了 xff0c 这时候我们要减少元素之间移动的次数了 表排序就是这么一个排序 xff0c
  • 循环链表的实现

    循环链表的实现 说明 参考资料 传智播客扫地僧的数据结构教学视频 线性表基本知识 参考 该实现的说明 C语言实现基于单向链表 xff0c 参考实现算法和数据的分离 实现 circular list h span class token ma
  • Ubuntu20.04安装与配置记录

    Ubuntu20 04安装与配置记录 原文地址 xff1a Ubuntu20 04安装与配置记录 一 Ubuntu系统盘制作 1 1 Windows环境下制作系统盘 下载Ubuntu系统 xff0c 选择桌面版 下载工具系统盘制作工具Ruf
  • C++单例写法记录

    C 43 43 单例写法记录 源码地址 一 饿汉式 1 1 静态指针 静态垃圾回收类 instance h ifndef INSTANCE H define INSTANCE H include lt string gt include l
  • 堆栈应用:表达式求值(C语言)

    文章目录 堆栈应用 xff1a 表达式求值 xff08 C语言 xff09 两个定义大致过程具体代码 堆栈应用 xff1a 表达式求值 xff08 C语言 xff09 两个定义 中缀表达式 xff1a 运算符号位于两个运算数之间 如 xff
  • andrsoid studio 长期编辑

    andrsoid studio 2020 02 08 修改build gradle配置 Top level build file where you can add configuration options common to all s
  • 使用 Maven 搭建 Mybatis 环境

    一 创建项目 1 点击 File gt New gt Module 2 选择左侧的 Maven xff0c 由于只是创建一个普通的项目 xff0c 此处点击 Next 即可 3 输入 GroupId 和 ArtifactId 4 配置 ma
  • ubuntu安装npm命令

    ubuntu安装npm命令 摘要 xff1a npm全称Node Package Manager xff0c 是node的包管理工具 xff0c 是用JavaScript写出来的工具 xff0c 被内置进了node中 xff0c 是随同No
  • zynq操作系统: Linux驱动开发AXIDMA篇

    前言 由于bram形式的速率限制 xff0c 在同样紧急的时间条件下 xff0c 还是改回了axidma的方式来降维打击 xff0c 对于几兆的速率 xff0c 颇有种杀鸡用牛刀的感觉 xff0c 没办法 xff0c 原来的刀就是差一点 x
  • C# 对RabbitMQ使用

    1 安装NuGet包RabbitMQ Client 2 生产者 确认机制 1 含义 xff1a 就是应答模式 xff0c 生产者发送一条消息之后 xff0c Rabbitmq服务器做了个响应 xff0c 表示收到了 2 特点 xff1a 异
  • CSS—— grid 网格布局

    文章目录 1 grid 网格布局 1 grid 网格布局 display gridgrid 属性是以下属性的简写属性 默认 grid gap xff0c none xff0c 200px 网格之间的距离grid template rows
  • 【图文解析】给定一个链表,判断链表中是否有环

    目录 例题描述解题思路代码实现 例题描述 给定一个链表 xff0c 判断链表中是否有环 为了表示给定链表中的环 xff0c 我们使用整数 pos 来表示链表尾连接到链表中的位置 xff08 索引从 0 开始 xff09 如果 pos 是 1
  • Centos7执行yum install *时出现“Peer‘s Certificate has expired.“

    一 引言 今天在安装OpenResty的时候 xff0c 出现了 34 Peer 39 s Certificate has expired 34 的问题 xff0c 详细错误如下 xff1a root 64 kubernetes sudo
  • git常用指令

    1 查看分支创建来源 指令 xff1a git reflog show 分支名 由图可以看出a分支是由master创建出来的 2 查看分支情况 查看远程分支 指令 xff1a git branch r 查看所有分支 指令 xff1a git
  • 利其器(2)——idea常用配置_提高开发效率

    文章目录 简介编码设置设置idea支持生成唯一序列化id全字母代码提示调出Run Dashboard显示方法分隔符忽略大小写提示自动导入包单行显示多个Tabs设置鼠标滚轮 43 96 ctrl 96 修改字体大小设置保存自动格式化等配置终端

随机推荐

  • 换硬币问题

    编写程序实现用一元人民币换成一分 xff0c 两分 xff0c 五分的硬币共50枚 三重循环 include lt stdio h gt int main int x y z x y z 分别表示一分 两分 五分的个数 for x 61 0
  • 最新ubuntu22.04 下列软件包有未满足的依赖关系 解决方案--------------------------------------------------记因为配环境而耽误的一天

    今天真的崩溃一整天了 xff0c 一直一直都在找错一直一直都在找解决方案 xff0c 我发现VM真的超多超多BUG的 xff0c 感兴趣的话可以跟我聊聊 当然这篇讲的主要不是这些BUG xff0c 而是依赖关系 如果你出现类似的情况 xff
  • python获取当前执行py文件的绝对路径

    python获取当前执行py文件的绝对路径 python3 home appuser test py span class token comment 获取当前执行py文件的绝对路径 span py file path span class
  • 【iOS】NSAttributedString 相关

    1 富文本的相关属性字段 NSAttributedString Key xff08 1 xff09 paragraphStyle span class token keyword let span paraStyle span class
  • python奇技淫巧:命令行输出漂亮的表格

    前言 最近想着用 Python写一个命令行的管理各种资源的信息的管理工具 xff0c 比如阿里云的ECS等信息 xff0c 基本的功能就是同步阿里云的资源的信息到数据库 xff0c 然后可以使用命令行查询 展现信息在命令行中的 xff0c
  • Android_基础_String资源带参数

    转载自 https www cnblogs com leelugen p 6685905 html Android 基础 String资源带参数 在android 开发 xff0c 我们通常会用string xml资源去设置textview
  • es6 — class 类,原型,原型链

    文章目录 1 意义2 语法1 由来2 constructor 3 类实例3 1 使用new 调用3 2类的继承 4 新写法5 取值函数 getter 存值函数 setter 2 原型以及原型链1 原型2 原型链3 instanceof 1
  • SQLServer注释快捷键

    SQLServer中的批量注释 批量注释批量取消注释 批量注释 Ctrl 43 K C 按住Ctrl键不放 然后依次按下K和C 批量取消注释 Ctrl 43 K U 按住Ctrl键不放 然后依次按下K和U
  • 【面试宝典】软件测试工程师2021烫手精华版(第一章测试理论篇)

    前言 xff1a 翻了很多论坛博客关于面试的文章 xff0c 很多都是不完整的 xff0c 还都是比较常见规规矩矩的 xff0c 那大家刷过的基本都不拿出来了 xff0c 都是一些大家平时见得不多 xff0c 但是面试官很看中的一些题 第一
  • uniapp package.json和mainfest.json,如何区分环境变量

    uniapp在hbuilder中 xff0c 导航的运行就是development xff0c 发行就是production package json 如果是往服务器上发布版本 xff0c 则是打包成zip在服务器上解压 xff0c 但注意
  • VSCode扩展时出错XHRfaile问题解决

    问题 VScode扩展插件链接网络失败XHR faile错误 解决办法 1 第一步 xff1a 文件 gt 首选项 gt 设置 gt 如下图 xff1a 2 第二步 xff1a 用户 gt 应用程序 gt 代理服务器 gt 如下图操作 xf
  • HDFS的启动流程和HA

    HDFS的启动流程 当 NameNode 启动时HDFS首先将Fsimage读入内存对元数据进行恢复 xff0c 然后再读edits文件中的更新操作在恢复后的元数据上进行执行 xff0c 使得此时的NameNode中保存的是停止前的最新状态
  • 『XXG笔记』Github pages 自定义域名

    x1f44b 本文章为我 XXG 原创 xff0c 由于个人能力有限 xff0c 此笔记可能会错漏 过时 或需要补充 x1f4d6 笔记文章由于多平台发布 xff0c 为了修改方便 xff0c 可以参观我的博客 xff1a https xx
  • 第十八篇,Simulink with Git

    一 综述 本篇以MATLAB R2021b为基础讲解如何对Simulink模型做Git管理 xff0c mdl与slx均可 Git并非只能对手写代码做版本管理 xff0c 它的应用十分广泛 xff0c 囊括了各种使用编程语言编写的代码 脚本
  • 第十九篇,解析法求解五阶多项式

    x0为初始约束 xff0c 时间为0 xff1b x1为结束约束 xff0c 时间为t coef 为求解结果 xff0c 定义x 61 at 5 43 bt 4 43 ct 3 43 dt 2 43 et 43 f xff0c 则coef
  • 第二十篇,Simulink使用痛点记录

    在工作实践中发现了MATLAB amp amp Simulink一些虽不致项目失败但的确很不方便的点 xff0c 记录下来以备持续研究 xff0c 并做分享 xff1b 都是个人认为比较基础的能力或者容易做到的特性 xff0c MATLAB
  • 第七篇(下),MPC工程化总结

    目录 一 引言 二 MPC的理解与实现 2 1 模型设计与实现 2 2 MPC工程实现步骤 三 参考资料 3 1 基础理论 3 2 Refer to Apollo 3 3 其它实例参考 3 4 MATLAB中的MPC 四 demo代码 一
  • es6 -- 解构赋值

    文章目录 1 数组的解构赋值 xff0c 按次序排列 xff0c 位置决定2 对象的解构赋值 xff0c 没有次序 xff0c 变量与属性同名即可取值 默认undefined3 字符串的解构赋值4 数值和布尔值的结构赋值5 函数结构赋值 被
  • 第二十一篇,常用Git操作记录

    一 拉取远程分支 拉取远程名叫dev的分支 git fetch origin dev 执行后本地git branch并不能看到dev git checkout dev 可以看到dev了 xff0c 在dev上开发 二 本地新建分支推送到远程
  • 第二十二篇,C++面经之问答(一)

    目录 一 传引用有没有拷贝 二 引用和指针的区别 三 构造 析构函数中可不可以调用虚函数 四 怎样区分继承和组合 五 多态的实现原理 虚表虚指针 六 用过哪些设计模式 6 1状态模式 6 2享元模式 6 3单例模式 6 4工厂模式 6 5观