• C++11中类与对象推出的新功能 [补充讲解final/override关键字]



    在这里插入图片描述

    1.移动构造

    在这里插入图片描述

    编译器自动生成移动构造

    在这里插入图片描述

    编译器没有自动生成移动构造

    在这里插入图片描述
    在这里插入图片描述

    2.移动赋值

    规则同上

    在这里插入图片描述

    对于移动构造/移动赋值的想法

    首先我们思考一下 一个什么样的类需要有移动构造?

    回答:一个涉及到深层拷贝的类 因为移动构造的本意就是当遇到右值拷贝时直接交换不再进行深层拷贝

    接着我们看为什么大佬这么设计移动构造自动生成的条件

    相比之前的默认成员函数 编译器自动生成的移动构造/移动赋值 条件更为苛刻 其实 C++大佬这样设计是完全有道理的 当一个类不需要析构\拷贝构造\赋值重载

    一个不需要析构/拷贝构造\赋值重载的类[一个不需要自己实现析构函数的类 基本上也不需要自己实现拷贝构造和赋值重载] 我们大概可以想象他的成员是这样的:一个内置类型一个自定义类型

    对于这样一个类 当我们没有自己实现移动构造 此时编译器会自动生成移动构造 自动生成的这个移动构造完全可以处理这个类的成员 [对于内置类型进行浅拷贝 对于自定义类型 有移动构造调用移动构造 没有调用拷贝构造]

    内置类型本来浅拷贝就行 自定义类型如果自己实现移动构造[当前类需要自己实现 那就自己实现一个] 那就调用移动构造 如果没有自己实现 说明当前类不需要移动构造或满足条件自动生成的就够用

    3.类成员定义时初始化

    C++11允许在类定义时给成员变量缺省值,默认生成的构造函数会使用这些缺省值初始化

    在这里插入图片描述

    4.强制生成默认函数的关键字default

    在这里插入图片描述
    C++11让我们能更好的控制要使用的默认函数。假设我们要使用某个默认的函数,但是因为一些原因这个函数没有默认生成。比如:

    1. 自己实现了拷贝构造 就不会自动生成 默认拷贝构造/无参构造/移动构造了,那么我们可以使用default关键字显示指定他们生成。
    2. 自己实现了有参构造 就不会自动生成默认无参构造 那么我们可以使用default关键字显示指定他生成
    class Person
    {
    public:
    Person(const char* name = "", int age = 0)
    :_name(name)
    , _age(age)
    {}
    //自己实现了拷贝构造 不会再自动生成移动构造
    Person(const Person& p)
    :_name(p._name)
    ,_age(p._age)
    {}
    //强制移动构造生成
    Person(Person&& p) = default;
    
    private:
    bit::string _name;
    int _age;
    };
    
    int main()
    {
    Person s1;
    Person s2 = s1;
    Person s3 = std::move(s1);
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    5.禁止生成默认函数的关键字delete

    5.1介绍

    如果我们自己与一个类 但是我们不想让别人调用我们这个类的拷贝构造 在C++98中我们可以将这个类的拷贝构造函数 访问属性设置为private 使得他人无法调用 在C++11中我们可以在该函数声明加上=delete,该语法指示编译器不生成对应函数的默认版本,称 =delete修饰的函数删除函数
    在这里插入图片描述

    5.2应用场景

    实现一个类 使得这个类只能在堆上创建对象[一个类创建的对象销毁时自动调用析构函数 如果这个对象的析构函数只能在堆区调用 那么我们的目的就达到]

    1.法一:析构函数私有化

    在这里插入图片描述

    2.法二: delete关键字

    在这里插入图片描述

    思考

    为什么new的对象可以存在?

    因为pre是个指针 是个内置类型 只有自定义类型的对象在销毁时才会自动调用析构 而内置类型不会 即析构函数能否调用 对内置类型无影响

    但是此时又引发一个问题 析构函数无法被调用 如果此类有这样的成员属性char* _str; 那么这个类就有资源需要手动释放[本来应该自己实现一个析构函数] 怎么办?

    废话不多说 直接上代码 一看便知

    class HeapOnly
    {
    public:
    	HeapOnly()
    	{
    		_str = new char[10];
    	}
    
    	~HeapOnly() = delete;
    
    	void Destroy()
    	{
    		delete[] _str;
    
    		operator delete(this);
    		//free(this);
    	}
    
    private:
    	char* _str;
    };
    
    int main()
    {
    	//堆上创建对象
    	HeapOnly* ptr = new HeapOnly;
    
    	//栈上创建对象
    	HeapOnly hp1;
    	//数据段上[静态区]创建对象
    	static HeapOnly hp2;
    
    	ptr->Destroy();
    	//operator delete(ptr);
    	//free(this);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述

    6.final关键字

    final:修饰父类虚函数,表示该虚函数不能再被重写
    在这里插入图片描述

    7.override关键字

    override: 检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错
    在这里插入图片描述

  • 相关阅读:
    6182. 反转二叉树的奇数层(层次遍历)
    浅谈如何向上管理
    前端开发基础
    测试开发:10分钟Flask快速入门【建议收藏】
    Dev C++编写C/C++程序 出现[Error] ld returned 1 exit status报错分析及解决
    【微信开发第二章】SpringBoot实现微信公众号普通消息和模板消息回复
    dubbo接口自动化用例性能优化
    Linux文件/目录高级管理二
    全家桶Spring、HikariCP、Mybatis和Oracle配置,你想要的都在这里
    Word如何任意页开始插入页码
  • 原文地址:https://blog.csdn.net/LHRan_ran_/article/details/133828975