C++ 面试考点(三)

点击蓝字

d7a3100fb165fb3b8df88ce8c857e0fa.png

关注我们

21、构造函数和析构函数可以调用虚函数吗,为什么

  • 在C++中,提倡不在构造函数和析构函数中调用虚函数;

  • 在构造函数和析构函数调用的所有函数(包括虚函数)都是编译时确定的, 虚函数将运行该类中的版本.

    • 因为父类对象会在子类之前进行构造,此时子类部分的数据成员还未初始化,因此调用子类的虚函数时不安全的,故而C++不会进行动态联编;

    • 析构函数是用来销毁一个对象的,在销毁一个对象时,先调用子类的析构函数,然后再调用基类的析构函数。所以在调用基类的析构函数时,派生类对象的数据成员已经销毁,这个时候再调用子类的虚函数没有任何意义。


22、构造函数的执行顺序?析构函数的执行顺序?构造函数内部干了啥?拷贝构造干了啥?

  • 构造函数顺序:

    • 基类构造函数。如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序,而不是它们在成员初始化表中的顺序。

    • 成员类对象构造函数。如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序。

    • 派生类构造函数。

  • 析构函数顺序:

    • 调用派生类的析构函数;

    • 调用成员类对象的析构函数;

    • 调用基类的析构函数。

23、虚析构函数的作用,父类的析构函数是否要设置为虚函数?

  • C++中基类采用virtual 虚析构函数是为了防止内存泄漏

    • 如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。

    • 假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。

    • 所以,为了防止这种情况的发生,`C++`中基类的析构函数应采用`virtual` 虚析构函数。


  • 纯虚析构函数一定得有定义,因为每一个派生类析构函数会被编译器加以扩张,以静态调用的方式调用其每一个虚基类以及上一层基类的析构函数。因此缺乏任何一个基类析构函数的定义,就会导致链接失败。==因此,最好不要把虚析构函数定义为纯虚析构函数。==


24、`构造函数``析构函数`可以调用虚函数吗?

  • 构造函数析构函数中最好不要调用虚函数;

  • 构造函数析构函数中调用的成员函数都是属于编译时确定的,并不具有虚函数的动态绑定特性, 有如下原因:

    • 在构造时, 父类对象总是先于子类对象构造的, 如果父类的析构函数使用虚函数机制调用子类的函数, 结果将是不可预料的

    • 在析构时, 子类的析构函数总是先于父类执行, 如果父类的析构函数使用虚函数机制调用子类的函数, 结果将是不可预料的


  • 参考: 21、构造函数和析构函数可以调用虚函数吗,为什么


25、`构造函数`, `析构函数`可否抛出异常

  • 构造函数异常

    • 使用智慧指针来管理堆内存. 其不需要在析构函数中手动释放资源. 在发生异常时, 智慧指针会自动释放资源从而避免了内存泄漏.

    • 一般建议不要在构造函数里做过多的资源分配。

    • (原因):`C++`拒绝为没有完成构造函数的对象调用析构函数,原因是避免开销

    • 构造函数中发生异常,控制权转出构造函数。如果构造函数中申请了堆内存, 则堆内存将无法释放, 从而造成内存泄漏

    • 例如: 在对象`b` 的构造函数中发生异常,对象`b` 的析构函数不会被调用。因此会造成内存泄漏

    • 后果:

    • 解决方案:

  • 析构函数异常

    • (后果1): 如果某一个异常发生,某对象的析构函数被调用,而此时析构发生了异常并流出了函数之外,则函数会被立即terminate掉(函数外有catch也不能拯救)

    • 如果异常不可避免,则应在析构函数内捕获,而不应当抛出。

    • 在析构函数中使用`try-catch`块屏蔽所有异常。

    • 在异常传递的堆栈辗转开解的过程中, 如果发生析构异常, `C++`会调用`terminate`终止程序

    • 如果析构函数发生发生异常,则异常后面的代码将不执行,无法确保完成我们想做的清理工作。

    • 后果:

    • 解决方法:

    • 附加说明:


26、类如何实现`只能静态分配`和`只能动态分配`

  • 建立类的对象有两种方式:

    • 动态建立类对象, 使用new操作符将在堆空间分配内存, 然后调用构造函数初始化这片内存空间.

    • 这种方法,间接调用类的构造函数

    • 静态建立一个类对象,就是由编译器为对象在栈空间中分配内存, 然后调用构造函数初始化这片内存空间.

    • 使用这种方法,直接调用类的构造函数

    • 静态建立(栈空间)

    • 动态建立(堆空间),A *p = new A();

  • 只能在堆上建立

    • 静态建立:

    • 编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性

    • 由此引发的问题:

    • 代码如下:

      class  A  {  protected :  A(){}  ~A(){}  public :  static  A* create()  {  return   new  A();  }  void  destory()  {  delete   this ;  }  };
    • 当对象建立在栈上面时,是由编译器分配内存空间的,调用构造函数构造栈对象。

    • 当对象使用后,编译器会调用析构函数释放栈对象所占的空间。

    • 编译器管理了对象的整个生命周期。

    • 其实不光是析构函数,只要是非静态的函数,编译器都会进行检查。

    • 如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。

    • 因此,将析构函数设为私有,类对象就无法建立在栈上了。

    • 因为析构函数设置为了私有

    • 需要设置一个public函数来调用析构函数

    • 分析: 类对象只能建立在堆上,就是不能静态建立类对象,即不能直接调用类的构造函数

    • 实现方式: 将析构函数设为私有或则受保护

    • 方法分析:

  • 只能在栈上建立

    • 只有使用new运算符,对象才会建立在堆上,因此,只要禁用new运算符就可以实现类对象只能建立在栈上。将operator new()设为私有即可

    • 注意: 重载了`new`就需要重载`delete`

    • 代码如下:

      class  A  {  private :  void * operator  new ( size_t  t){}      // 注意函数的第一个参数和返回值都是固定的   void  operator  delete ( void * ptr){}  // 重载了new就需要重载delete   public :  A(){}  ~A(){}  };

  • 参考:

    • 在堆/栈上建立对象

    • 如何定义一个只能在堆上(栈上)生成对象的类?


27、如果想将某个类用作基类,为什么该类必须定义而非声明?

  • 因为在继承体系下, 子类会继承父类的成员, 并且编译器会在子类的构造函数和析构函数中插入父类的构造和析构部分, 因而父类必须有定义.

28、什么情况会自动生成默认构造函数?

  • 四种情况:

    • 类成员对象带有默认构造函数.

    • 基类带有默认构造函数

    • 类中存在虚函数

    • 继承体系中存在虚继承

  • 在合成的默认构造函数中,只有基类子对象和类类型对象会被初始化,而其他所有的非静态成员(如整数,指针,数组等),都不会初始化,对他们进行初始化的应该是程序员,而非编译器。

  • 注意:值类型的默认值并不是默认构造的初始化。


29、什么是类的继承?

  • 类与类之间的关系

    • `(has-A)`包含关系,即一个类的成员属性是另一个已经定义好的类

    • `(use-A)`使用关系, 一个类使用另一个类,通过类之间的成员函数相互联系,定义友元或者通过传递参数的方式实现;

    • `(is-A)`继承关系, 继承关系,关系具有传递性;

  • 继承的相关概念

    • 所谓的继承就是一个类继承了另一个类的属性和方法,这个新的类包含了上一个类的属性和方法,

    • 被称为子类或者派生类,被继承的类称为父类或者基类;

  • 继承的特点

    • 子类拥有父类的所有属性和方法,子类对象可以当做父类对象使用;

    • 子类可以拥有父类没有的属性和方法;

  • 继承中的访问控制

    • `public`、`protected`、`private`

  • 继承中的构造和析构函数

    • 子类中构造函数的调用顺序为: 基类构造函数, 成员对象构造函数, 派生类构造函数

    • 子类中析构函数的调用顺序为: 派生类析构函数, 成员对象析构函数, 基类析构函数

  • 继承中的兼容性原则

    • 类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代。

    • 参考: 继承中的类型兼容性原则 - Say舞步 - 博客园

30、什么是组合?

  • 一个类里面的数据成员是另一个类的对象,即内嵌其他类的对象作为自己的成员;

  • 如果内嵌类没有零参数构造函数, 则必须使用初始化列表进行初始化

  • 构造函数的执行顺序:

    • 按照内嵌对象成员在组合类中的定义顺序调用内嵌对象的构造函数。

    • 然后执行组合类构造函数的函数体,析构函数调用顺序相反。

*声明:本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

4a539f7a6d4aa0f835663ce4ec9ad826.png

de1dbdedd9f9719322320ae6ddca0021.gif

戳“阅读原文”我们一起进步

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

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

相关文章

用终端访问路由器设置端口开发_serial for mac(终端管理软件)v2.0.3

原标题:serial for mac(终端管理软件)v2.0.3serial for mac是应用在Mac上的一款终端管理软件,可以帮助您连接和控制串行设备,如服务器,路由器或调制解调器等网络设备,PBX系统等。好消息是Serial为大多数串行设备提供了…

大神级的C++性能优化,你能看懂吗?

点击蓝字关注我们一、前言性能优化不管是从方法论还是从实践上都有很多东西,文章会从C语言本身入手,介绍一些性能优化的方法,希望能做到简洁实用。二、实例1在开始本文的内容之前,让我们看段小程序:// 获取一个整数对应…

钢笔墨水能否代替打印机墨水_LAMY钢笔应该如何选择墨水?

其实墨水世面上基本是有两种:碳素墨水和非碳素。碳素墨水相对比较堵笔,碳素墨水对钢笔本身腐蚀性不大,腐蚀性大的那是染料/颜料墨水。碳素墨水写字非常容易有笔锋,而非碳素墨水就显得略微柔和了。有人说,字写得好的人用…

html ctf查找,Web CTF 解题思路总结—南京邮电大学攻防平台writeup

1、直接查看源代码例:签到题(50)2、PHP的特性(1)MD5 碰撞例:md5 collision(50)md5碰撞:MD5摘要算法可以从多个字节组成的串中计算出由32个字节构成的“特征串”,对于超过32字节的串来说,MD5计算得出的值必然是其一个子…

java 1.8新增功能_睡觉时:新增的Java 8新增功能

java 1.8新增功能自Java 8推出以来,最有趣的功能是什么? Java 8最近庆祝了它的第一个生日,其主要版本已经在一年多以前了。 这当然值得庆祝。 自从最初的Java 8版本问世以来,已经发布了六个更新。 这些更新中的某些元素是次要的…

C++ 为什么不加入垃圾回收机制

点击蓝字关注我们Java的爱好者们经常批评C中没有提供与Java类似的垃圾回收(Gabage Collector)机制(这很正常,正如C的爱好者有时也攻击Java没有这个没有那个,或者这个不行那个不够好),导致C中对动态存储的官吏称为程序员的噩梦,不是…

c++ 共享内存_Python3.8多进程之共享内存

最近发了个宏愿想写一个做企业金融研究的Python框架。拖出Python一看已经更新到了3.8,于是就发现了Python 3.8里新出现的模块:multiprocessing.shared_memory。随手写了个测试。生成一个240MB大小的pandas.DataFrame,然后转换成numpy.recarra…

计算机主机箱外部介绍图,电脑的主机结构是怎样的 电脑主机结构图【图文】...

在电脑已经普及的今天,基本上每家每户都有电脑了,大家用它来看电影,搜索资料啊,上网啊等等。在我们日常的娱乐方式中,电脑也是我们的娱乐项目之一,至少还是好多人用它看电影和追剧的。但是机器会有故障的时…

C 语言各数据类型的内存映像

点击蓝字关注我们C语言各种数据类型的内存映像&#xff08;32位平台&#xff09;&#xff1a;0 signed char#include <stdio.h> int main() {char min 1<<7;char max (1<<7)-1;for(int imin;i<max;i)if(i<0)printf("%.2X ",(unsigned char…

用java编写一个图书管理系统_手把手教你编写第一个java程序

安装完jdk后我们就可以试着编写第一个java程序了&#xff0c;让我们一起来试试吧&#xff01;第一步点击开始——所有程序——附件——记事本&#xff0c;新建记事本&#xff0c;输入以下代码&#xff1a;class HelloWorld { public static void main(String args[]) { System.…

go micro java_Java Micro Framework:您无法忽略的新趋势

go micro java什么是Java微框架&#xff0c;为什么要使用它们&#xff1f; 每种语言都有权衡。 对于Java&#xff0c;要成为一种安全&#xff0c;经过严格测试&#xff0c;向后兼容的语言&#xff0c;就要在敏捷性和简化方面做出一些牺牲。 无可否认&#xff0c;有些冗长和冗长…

C语言调用C++类成员函数讲解和实例

点击蓝字关注我们1、问题成因C语言与C调用问题原因主要在于C编译器和C编译器的不同。C是过程式语言&#xff0c;C编译器编译后&#xff0c;函数在符号库中就是函数名&#xff0c;没有其他任何附加信息。而C是对象式语言&#xff0c;支持函数重载&#xff0c;C编译器编译后&…

学生命科学要学计算机吗,现在学生物学出路真的有那么不济吗?

最近浏览知乎&#xff0c;看到大规模的生物劝退贴&#xff0c;这些帖子纷纷拿出多个例子&#xff0c;并现身说法&#xff0c;告诫学生物的同学尽早转行&#xff0c;并声称劝退一人胜发7篇CNS。作为网友盛传的天坑之首&#xff0c;生物专业到底有多坑&#xff1f;环球科学曾对北…

java笔试题_Java面试才到笔试就没有然后了?快来签收,高频笔试57题及解答

前言很多人面试之前&#xff0c;可能没有在互联网公司工作过或者说工作过但年头较短&#xff0c;不知道互联网公司技术面试都会问哪些问题&#xff1f; 再加上可能自己准备也不充分&#xff0c;去面试没几个回合就被面试官几个问题打蒙了&#xff0c;甚至笔试都过不了。最后以惨…

java开发错误_每个Java开发人员都必须避免的9个安全错误

java开发错误Checkmarx CxSAST是功能强大的源代码分析&#xff08;SCA&#xff09;解决方案&#xff0c;旨在从根本上识别&#xff0c;跟踪和修复技术和逻辑安全漏洞&#xff1a;源代码。 在这里查看 &#xff01; 自从1995年中期引入Java以来​​&#xff0c;它已经走了很长一…

C语言中常用的标准库函数有哪些?

点击蓝字关注我们标准头文件包括&#xff1a;<asset.h> <ctype.h> <errno.h> <float.h> <limits.h> <locale.h> <math.h> <setjmp.h> <signal.h> <stdarg.h> <…

计算机考试一级考试基础知识,全国计算机等级考试一级msoffice基础知识

全国计算机等级考试一级msoffice基础知识导语&#xff1a;在日常生活中&#xff0c;媒体(Medium &#xff0c;复数形式为Media )是指文字、声音、图像、动画和视频等内容。多媒体(Multimedia )是指能够同时对两种或两种以上媒体进行采集、操作、编辑、存储等综合处理的技术。多…

2008铁路旅客列车时刻表_天津到新沂汽车卧铺大巴车长途汽车发车时刻表

长途大巴网上需要注意什么&#xff01;选择乘坐大巴&#xff0c;是大家出行时的一个好选择&#xff0c;而且长途大巴网上也 很方便&#xff0c;能让大家节省不少的时间&#xff0c;但是网上有许多的要求&#xff0c;可能大家还不清楚。小编就给大家 介绍下长途大巴网上须知。长…

web ua检测_UA Web挑战会议:针对初创公司的SpringIO

web ua检测在本周&#xff0c;我在“后端”部分的UA Web挑战会议上发表了讲话。 我在演讲中选择了一个奇怪的话题-“面向初创企业的SpringIO”。 结果是什么&#xff1f; 我将在下面总结。 在过去三年中&#xff0c;我开发了各种个人Web项目。 我再也没有称它们为“初创公司”…

手把手教你撸一个线程池 - C++版

点击蓝字关注我们前面的文章在手把手教你写 C 语言线程池中&#xff0c;已经实现了 C 语言版的线程池&#xff0c;如果我们也学过 C 的话&#xff0c;可以将其改为 C 版本&#xff0c;这样代码不管是从使用还是从感观上都会更简洁一些。对这些代码做从 C 到 C 的迁移主要用到了…