当前位置: 首页 > news >正文

【C++ 面试 - 面向对象】每日 3 题(十二)

 ✍个人博客:Pandaconda-CSDN博客

📣专栏地址:http://t.csdnimg.cn/fYaBd

📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

 34. 构造函数和析构函数可否抛出异常?

1. C++ 只会析构已经完成的对象,对象只有在其构造函数执行完毕才算是完全构造妥当。在构 造函数中发生异常,控制权转出构造函数之外。

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

  • 用 auto_ptr 对象来取代指针类成员,便对构造函数做了强化,免除了抛出异常时发生资源泄漏的危机,不再需要在析构函数中手动释放资源;

  • 如果控制权基于异常的因素离开析构函数,而此时正有另一个异常处于作用状态,C++ 会调用 terminate 函数让程序结束;

2. 如果异常从析构函数抛出,而且没有在当地进行捕捉,那个析构函数便是执行不全的。如果析构函 数执行不全,就是没有完成他应该执行的每一件事情。

在析构函数内部处理异常:

  

上面左边的方法是直接调用 abort 终止程序,右边则是直接吞下异常,只是记录个日志,后面再处理。

但是这两种方法都有个缺点就是用户无法参与操作,因此可以写成下面的方式:

  

用户可以自己实现一个 close 函数来进行关闭,如果关闭的顺利则 closed=true,反之关闭失败则会进行异常捕捉,在析构函数中帮助用户关闭。

总结:

析构函数可以抛出异常,但是这种做法是非常危险的,通常不推荐。因为析构函数具有一种清理资源的特性,如果析构函数本身抛出异常,可能导致以下问题:

  • 资源泄露:当一个对象被析构时,析构函数负责释放该对象持有的资源。如果析构函数抛出异常,这个过程可能会中断,导致资源泄露。

  • 叠加异常:如果析构函数在处理另一个异常时抛出异常,会导致异常叠加。这种情况下,程序将无法处理两个异常,从而可能导致未定义行为或程序崩溃。

为了避免这些问题,通常建议在析构函数中处理异常或者避免执行会抛出异常的函数,可以在析构函数中使用 try-catch 块来捕获和处理潜在的异常,确保资源得到正确释放和清理保证程序的稳定性和健壮性。

35. 构 造函数的几种关键字

default

default 关键字可以显式要求编译器生成合成构造函数,防止在调用时相关构造函数类型没有定义而报错。

#include <iostream>
using namespace std;class CString
{
public:CString() = default; //语句1//构造函数CString(const char* pstr) : _str(pstr){}void* operator new() = delete;//这样不允许使用new关键字//析构函数~CString(){}
public:string _str;
};int main()
{auto a = new CString(); //语句2cout << "Hello World" <<endl;return 0;
}
//运行结果
//Hello World

如果没有加语句 1,语句 2 会报错,表示找不到参数为空的构造函数,将其设置为 default 可以解决这个问题。

delete

delete 关键字可以删除构造函数、赋值运算符函数等,这样在使用的时候会得到友善的提示。

#include <iostream>
using namespace std;class CString
{
public:void* operator new() = delete;//这样不允许使用new关键字//析构函数~CString(){}
};int main()
{auto a = new CString(); //语句1cout << "Hello World" <<endl;return 0;
}

在执行语句 1 时,会提示 new 方法已经被删除,如果将 new 设置为私有方法,则会报惨不忍睹的错误,因此使用 delete 关键字可以更加人性化的删除一些默认方法

0

将虚函数定义为纯虚函数(纯虚函数无需定义,= 0 只能出现在类内部虚函数的声明语句处;当然,也可以为纯虚函数提供定义,函数体可以定义在类的外部也可以定义在内部)。

36. 构造函数、拷贝构造函数和赋值操作符的区别

构造函数

对象不存在,没用别的对象初始化,在创建一个新的对象时调用构造函数

拷贝构造函数

对象不存在,但是使用别的已经存在的对象来进行初始化

赋值运算符

对象存在,用别的对象给它赋值,这属于重载 "=" 号运算符的范畴,"=" 号两侧的对象都是已存在的

举个例子:

#include <iostream>
using namespace std;class A
{
public:A(){cout << "我是构造函数" << endl;}A(const A& a){cout << "我是拷贝构造函数" << endl;}A& operator = (A& a){cout << "我是赋值操作符" << endl;return *this;}~A() {};
};int main()
{A a1; //调用构造函数A a2 = a1; //调用拷贝构造函数a2 = a1; //调用赋值操作符return 0;
}
//输出结果
//我是构造函数
//我是拷贝构造函数
//我是赋值操作符


http://www.mrgr.cn/news/7209.html

相关文章:

  • 16 函数的基本概念、声明与调用、返回值、值传递、原型声明,文档注释,多文件编程(简易版)
  • 【编程之路:在 Bug 的迷宫中寻找出口】
  • STM32——PWM波形输出
  • 文件IO和多路复用IO
  • tcp 网络通信及抓包工具的使用
  • MySQL 1130错误原因及解决方案
  • 如何选择高品质科研实验室用太阳光模拟器
  • 【Android笔记】Android APK编译打包流程
  • 【TS】5 在React中使用TS
  • 推荐一个java低代码开发平台-橙单
  • ffmpeg.exe命令行常见应用
  • 金蝶云星空开发简单账表《物料年采购入库报表》
  • pyro 教程 时间序列 单变量,重尾,python pytorch,教程和实例 Forecasting预测,布朗运动项、偏差项和协变量项
  • 19.缓存的认识和基本使用
  • AMEYA360:芯讯通5G RedCap+智慧电力,SIM8230“轻”装上阵
  • 分析Facebook在区块链技术中的应用与前景
  • 谷歌chrome浏览器显示“版本太旧”又无法更新情况下,如何关闭“Chrome版本太旧”提示,包括直接启动Google浏览器,或者通过其他应用启动
  • 解决使用matplotlib不显示中文的问题
  • Android系统架构
  • 神经网络动画讲解 - 神经网络工作流程