| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> [Effective C++]第2章构造/析构/赋值运算 -> 正文阅读 |
|
[C++知识库][Effective C++]第2章构造/析构/赋值运算 |
条款05 了解C++默默编写并调用那些函数如果自己没有声明,那么C++会为类声明一个构造、一个copy构造、一个析构和一个赋值运算符重载。这些函数都是public inline的。default构造函数和析构函数主要是给编译器一个地方来放置调用基类和non-static成员变量的构造函数和析构函数。编译器产出的析构函数是non-virtual。而copy构造和=运算符重载只是单纯的将源对象的每一个non-static成员变量拷贝到目标对象。 当遇到一下三种情况,必须自定义=赋值重载运算符: 1、类中有常量;2、类中有引用数据;3、基类将=重载设置为private。 遇到以上三种情况,编译器都会拒绝为类生成一个=运算符重载。
很明显,引用数据nameValue和常量objectValue在被初始化之后就不能更改了,所以默认的=重载生成的语法就违反规则了,所以编译器就不会为其生成=重载。而基类将private设置为私有的情况下,若对子类对象进行赋值操作,默认=重载会调用基类的=重载,所以编译器也不允许这种操作。 条款06:若不想使用编译器自动生成的函数,就该明确拒绝如果想要拒绝类对象的复制行为,有两种做法: 1、将拷贝构造函数和=运算符重载函数设置为private,并且不实现它们; 2、继承一个将拷贝构造函数和=运算符重载函数设置为private的类
条款07:为多态基类声明virtual析构函数如果多态基类的析构函数是non-virtual的,会出现一下情况:
如上所述,当delete bp对象的时候,会调用Base的析构函数,而Derived对象没有得到释放。 解决这种问题的方法就是将基类的析构函数声明为virtual,这样dp就会调用Derived对象的析构函数,而Derived对象的析构函数也会调用父类的析构函数,这样所有的内存才得以释放完毕。 当然只有类中含有virtual函数时才需要将析构函数声明为virtual。因为每个带有虚函数的类,其生成的对象都会有一个指向虚函数表的虚函数指针,通过这个指针可以查询到如何调用虚函数。而如果对于没有virtual的类设置virtual析构函数,会造成其对象多了一个虚函数指针,这个指向可能是32位的,也可能是64位的。 条款08:别让异常逃离析构函数?析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下他们或结束程序。如下:
如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么class应该提供一个普通函数执行该操作。 条款09:绝不在构造和析构过程中调用virtual函数设想在一个父类指针指向子类对象的指针,这个类的构造函数中调用一个virtual函数,而两个类都实现了这个virtual函数,那么父类指针的构造函数会直接调用子类的virtual函数吗? 答案是NO!!!因为父类对象是先于子类对象创建的,而子类对象都没有创建,去哪调用子类的virtual函数?因此父类指针调用的是父类的virtual函数。。。 那么将上述问题的构造函数换成析构函数,父类的析构函数中调用了virtual函数,那么父类指针调用的是父类的virtual还是子类的virtual函数呢? 答案还是父类。因为子类对象的析构函数先于父类对象的析构函数调用,等程序运行到父类对象的析构函数时,子类对象已经没了,因此父类对象只能调用自己的virtual。 条款10:令operator= 返回一个reference to *thisC++中赋值采用右结合律,即x=y=z=15实际上是x=(y=(z=15)),为了实现这种连锁赋值,需要将=运算符重载返回一个*this。这个规则使用于所有的赋值相关运算符重载,如+=等等。 条款11:在operator=中处理“自我赋值” ?在operator=中如果出现当前对象跟赋值对象相同时,如下所示,如果没有自我检查,那么先把pb删了,在将pb赋给自己,肯定会发生错误。一下有3种方法处理自我赋值。 Method 1是证同测试,但是如果new BitMap(*rhs.pb)发生了异常,那么pb已经没了,无法拯救。Method 2在复制pb所指的东西之后再删除pb,即使new BitMap(*rhs.pb)发生了异常,pb依然存在
条款12:赋值对象时勿忘其每一个部分对于copy构造函数和=操作符重载,不仅要考虑其深度拷贝,还需要考虑其父类对象的拷贝,如果不对其父类对象进行拷贝,那么编译器会调用父类对象的default构造函数进行初始化。 解决问题的方法就是调用基类内的适当copying函数。
不要让拷贝构造与=运算符重载相互调用。 首先明确:拷贝构造函数的存在意义是通过已有的对象构造新的对象,构造完毕后才有两个对象;重载赋值操作符的意义在于将一个对象的值赋给另一个对象,两个对象都已经构造完毕了。 拷贝构造函数调用重载赋值操作符:把已有对象的值赋给一个构造中的对象,虽然这个对象的内存已经分配好了。(可以接受,但是有可能导致循环调用重载赋值操作符和拷贝构造函数) 重载赋值操作符调用拷贝构造函数:把已有对象复制并赋值给这个对象。——多一个临时对象,而且导致循环调用重载赋值操作符。重载赋值操作符调用拷贝构造函数会导致循环调用重载赋值操作符? |
|
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/24 4:45:51- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |