| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 构造函数与析构函数的问题总结 -> 正文阅读 |
|
[C++知识库]构造函数与析构函数的问题总结 |
目录 C++中有哪些构造函数构造函数的定义构造函数被使用来对象创造时的初始化工作,即在构造函数中为对象赋初值。 C11前是不允许成员变量定义时就初始化的操作(C11之后是允许的,原理请参考C11中类成员变量定义时初始化问题),例如
因此就设计通过构造函数还在实例化对象时初始化成员变量。如下几种常见的构造函数 构造函数的分类
程序例如:
输出结果: 构造函数相关问题问题一:什么情况下会调用拷贝构造函数?除了上面初始化类对象时通过引用传递对象会调用拷贝构造函数的情况,还有以下几种特殊情况也会调用拷贝构造函数。 情况1:使用“=”,用类的一个实例化对象去初始化另一个对象的时候 情况2:函数的参数是类的对象,并且不是引用传递(此处是函数参数,不是类对象初始化) 情况3:函数的返回值是函数体内的局部类对象时 ,且返回方式是值传递,会在返回值的地方调用拷贝构造函数 例如:
结果: 从结果可以看到Solution b = a; 和function1(b);都调用了拷贝构造函数。 情况3这种情况,如下面这种形式:
这种情况在不同的平台会有不同的结果,在Linux中使用g++时返回局部对象不会调用拷贝构造函数;在windows中使用visual studio 2019时,返回局部对象,且是值传递会调用拷贝构造函数。 问题二:赋值初始化和列表初始化的区别?像默认构造函数,拷贝构造函数这类使用赋值初始化操作的是通过在函数体内进行赋值初始化;列表初始化在冒号后使用初始化列表进行初始化。 主要区别在于数据初始化的时间不同: 赋值初始化是在所有的数据成员被分配内存空间后才进行的。 列表初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),就赋值。分配一个数据的空间就初始化赋值。 注意:列表初始化时成员变量的初始化顺序是以数据成员的声明顺序一致。与列表初始化的顺序无关 问题三:构造函数和析构函数的执行顺序 ?构造函数: 作为一个继承了父类的派生子类,子类实例化对象时构造函数的执行顺序如下: ① 虚拟基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。 ② 基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)。 ③派生类类型的成员对象的构造函数(按照初始化顺序) ④ 派生类自己的构造函数。 析构函数: ① 调用派生类的析构函数; ② 调用派生类成员类对象的析构函数; ③ 调用基类的析构函数。 ④ 调用虚拟基类的析构函数。 问题四:构造函数能否声明为虚函数或者纯虚函数,析构函数呢?构造函数: 构造函数不能定义为虚函数。在构造函数中可以调用虚函数,不过此时调用的是正在构造的类中的虚函数,而不是子类的虚函数,因为此时子类尚未构造好。 原因:虚函数对应一个vtable(虚函数表),类中存储一个vptr指向这个vtable。如果构造函数是虚函数,就需要通过vtable调用,可是对象没有初始化就没有vptr,无法找到vtable,所以构造函数不能是虚函数。 析构函数: 析构函数可以为虚函数,并且一般情况下基类析构函数要定义为虚函数。 原因:从上面析构函数的调用顺序可知,首先要调用派生子类的析构函数。因此只有在基类析构函数定义为虚函数时,调用操作符delete销毁指向对象的基类指针时,才能准确调用派生类的析构函数(从该级向上按序调用虚函数),才能准确销毁数据。 析构函数可以是纯虚函数,含有纯虚函数的类是抽象类,此时不能被实例化。但派生类中可以根据自身需求重新改写基类中的纯虚函数。 问题五:构造函数、析构函数、可否声明为内联函数inline首先,将这些函数声明为内联函数,在语法上没有错误。但是《Effective C++》指出:将构造函数和析构函数声明为inline是没有什么意义的,编译器并不真正对声明为inline的构造和析构函数进行内联操作,因为编译器会在构造和析构函数中添加额外的操作(申请/释放内存,构造/析构对象等),致使构造函数/析构函数并不像看上去的那么精简,因此不会使用inline功能。 问题六:构造函数和析构函数可以调用虚函数吗?在C++中,可以调用,但不提倡; ① 我们调用虚函数,一般就是使用其动态联编的功能。但是构造函数和析构函数调用虚函数时都不使用动态联编,如果在构造函数或析构函数中调用虚函数,则运行的是为构造函数或析构函数自身类型定义的版本; ② 构造函数时,因为父类对象会在子类之前进行构造,此时子类部分的数据成员还未初始化,因此C++不会进行动态联编; ③析构函数是用来销毁一个对象的,在销毁一个对象时,先调用子类的析构函数,然后再调用基类的析构函数。所以在调用基类的析构函数时,派生类对象的数据成员已经销毁,也没有使用动态联编。 问题七:什么情况会自动生成默认构造函数?前提:如果类没有构造函数,编译器不一定会生成默认的构造函数,只有在构造函数真正被需要的时候才会生成; ① 如果一个类没有任何构造函数,但它含有一个带有默认构造函数的成员对象,那么在实例化该类时,编译器就为该类合成出一个默认构造函数。 原因:如果一个类A含有多个成员类对象的话,编辑器在给A类生成无参的默认构造函数的初始化列表的位置调用类对象的构造函数,完成对对象成员的初始化。且必须按照类对象在类A中的声明顺序进行;
② 带有默认构造函数的基类,如果一个没有构造函数的派生类继承自一个带有默认构造函数基类,那么该派生类会合成一个构造函数调用上一层基类的默认构造函数;
③带有一个虚函数的类 原因:含有虚函数的类都拥有一个虚指针vptr。编译器需要设置vptr。因此需要生成默认构造函数,设置vptr的初值。 ④ 带有一个虚基类的类 问题八:为什么拷贝构造函数必须传引用不能传值?例如:
原因:如果用传值的方式进行传参数,那么构造实参 ”Soulution s“ 需要调用拷贝构造函数,而拷贝构造函数需要传递实参,实参中又要调用拷贝构造函数,会一直递归。所以拷贝构造不允许使用值传递。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 21:44:29- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |