类的新功能

类的新功能

默认成员函数

在C++11之前,一个类中有如下六个默认成员函数:

  1. 构造函数。
  2. 拷贝构造函数
  3. 赋值重载
  4. 析构函数
  5. 取地址重载函数
  6. const取地址函数

其中前四个默认成员函数最重要,后面两个默认成员函数一般不会用到,这里默认成员函数是我们不写编译器会自动生成的函数。在C++11标准中又增加了两个默认成员函数,分别是移动构造函数和移动赋值重载函数。

移动构造函数的生成条件:自己没有实现移动构造函数,并且自己没有实现析构函数拷贝构造函数赋值重载函数
移动赋值重载函数的生成条件:自己没有实现移动赋值重载函数,并且自己没有实现析构函数拷贝构造函数赋值重载函数

因此我们需要注意的是:移动构造和移动赋值的生成条件与之前六个默认成员函数不同,并不是单纯的没有实现移动构造和移动赋值,编译器就会默认生成

默认生成的移动构造函数:对于内置类型的成员会完成值拷贝(浅拷贝),对于自定义类型的成员,如果该成员实现了移动构造就调用它的移动构造,否则就调用它的拷贝构造。
默认生成的移动赋值重载函数:对于内置类型的成员会完成值拷贝(浅拷贝),对于自定义类型的成员,如果该成员实现了移动赋值就调用它的移动赋值,否则就调用它的赋值重载。

我们实现一个简化版的string来验证默认生成的移动构造和移动赋值重载函数的功能实现。

namespace a
{class string{public://构造函数string(const char* str = ""){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}//交换两个对象的数据void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//拷贝构造函数(现代写法)string(const string& s):_str(nullptr), _size(0), _capacity(0){cout << "string(const string& s) -- 深拷贝" << endl;string tmp(s._str);swap(tmp);}//移动构造string(string&& s):_str(nullptr), _size(0), _capacity(0){cout << "string(string&& s) -- 移动构造" << endl;swap(s);}//赋值重载函数(现代写法)string& operator=(const string& s){cout << "string& operator=(const string& s) -- 深拷贝" << endl;string tmp(s);swap(tmp);return *this;}//移动赋值string& operator=(string&& s){cout << "string& operator=(string&& s) -- 移动赋值" << endl;swap(s);return *this;}//析构函数~string(){//delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}private:char* _str;size_t _size;size_t _capacity;};
}

然后我们再编写一个简单的Person类

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& operator=(const Person& p){if (this != &p){_name = p._name;_age = p._age;}return *this;}//析构函数~Person(){}
private:a::string _name;int _age; 
};

虽然Person类当中没有实现移动构造和移动赋值,但拷贝构造、拷贝赋值和析构函数Person类都实现了,因此Person类中不会生成默认的移动构造和移动赋值,可以通过下面的代码来验证:

int main()
{Person s1("张三", 21);Person s2 = move(s1); //想要调用Person默认生成的移动构造return 0;
}

上述代码中用一个右值去构造s2对象,但由于Person类没有生成默认的移动构造函数,因此这里会调用Person的拷贝构造函数(拷贝构造既能接收左值也能接收右值),这时在Person的拷贝构造函数中就会调用string的拷贝构造函数对name成员进行深拷贝。

如果要让Person类生成默认的移动构造函数,就必须将Person类中的拷贝构造、拷贝赋值和析构函数全部注释掉,这时用右值去构造s2对象时就会调用Person默认生成的移动构造函数。

  • Person默认生成的移动构造,对于内置类型成员age会进行值拷贝,而对于自定义类型成员name,因为我们的string类实现了移动构造函数,因此它会调用string的移动构造函数进行资源的转移。
  • 而如果我们将string类当中的移动构造函数注释掉,那么Person默认生成的移动构造函数,就会调用string类中的拷贝构造函数对name成员进行深拷贝。

要验证Person类中默认生成的移动赋值函数可以用下面的代码,验证方式和上面验证移动构造的方式是一样的。

int main()
{Person s1("张三", 21);Person s2;s2 = std::move(s1); //想要调用Person默认生成的移动赋值return 0;
}

类成员变量初始化

默认生成的构造函数,对于自定义类型的成员会调用其构造函数进行初始化,但并不会对内置类型的成员进行处理。于是C++11支持非静态成员变量在声明时进行初始化赋值,默认生成的构造函数会使用这些缺省值对成员进行初始化。

class Person
{
public://...
private://非静态成员变量,可以在成员声明时给缺省值,用于给默认构造函数进行初始化string _name = "张三";int _age = 20;static int _n; //静态成员变量不能给缺省值
};

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

C++11可以让我们更好地控制要使用的默认成员函数,假设在某些情况下我们需要使用某个默认成员函数,但是因为某些原因导致无法生成这个默认成员函数,这时可以使用default关键字强制生成某个默认成员函数。下面我们来看一个场景。

class Person
{
public://拷贝构造函数Person(const Person& p):_name(p._name), _age(p._age){}
private:string _name; //姓名int _age;         //年龄
};

这时就会报错,因为Person类中已经有了拷贝构造函数,导致无法生成默认构造函数,因为默认构造函数生成的条件是没有编写任意类型的构造函数,包括拷贝构造函数。

int main()
{Person s; //没有合适的默认构造函数可用return 0;
}

这时我们就可以使用default关键字强制生成默认的构造函数。

class Person
{
public:Person() = default; //强制生成默认构造函数//拷贝构造函数Person(const Person& p):_name(p._name), _age(p._age){}
private:string _name; int _age;         
};

 默认成员函数都可以用default关键字强制生成,包括移动构造和移动赋值。

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

当我们想限制默认函数生成,可以通过如下两种方式:

  1. 在C++98中,可以将该函数设置成私有,并且只用声明不用定义,这样当外部调用该函数时就会报错。
  2. 在C++11中,可以在该函数声明后面加上=delete,表示让编译器不生成该函数的默认版本,我们将=delete修饰的函数称为删除函数。


例如,要让一个类不能被拷贝,可以用=delete修饰将该类的拷贝构造和赋值重载。

class CopyBan
{
public:CopyBan(){}
private:CopyBan(const CopyBan&) = delete;CopyBan& operator=(const CopyBan&) = delete;
};

注意:被=delete修饰的函数可以设置为公有,也可以设置为私有,效果都一样。

继承和多态中final与override关键字

被final修饰的类叫做最终类,最终类无法被继承。

class NonInherit final //被final修饰,该类不能再被继承
{//...
};

final修饰虚函数,表示该虚函数不能再被重写,如果子类继承后重写了该虚函数则编译报错。

//父类
class Person
{
public:virtual void Print() final //被final修饰,该虚函数不能再被重写{cout << "hello Person" << endl;}
};
//子类
class Student : public Person
{
public:virtual void Print() //重写,编译报错{cout << "hello Student" << endl;}
};

override修饰子类的虚函数,检查子类是否重写了父类的某个虚函数,如果没有重写则编译报错。

//父类
class Person
{
public:virtual void Print(){cout << "hello Person" << endl;}
};
//子类
class Student : public Person
{
public:virtual void Print() override //检查子类是否重写了父类的某个虚函数{cout << "hello Student" << endl;}
};

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

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

相关文章

c++的输入输出与判断

c是一门高级语言&#xff0c;从本篇起我将依次介绍c的各种知识。 在第一节课&#xff0c;我们要介绍c输入语句、输出语句、判断语句。 注明&#xff1a;在本篇中都使用下面的框架&#xff0c;在下一篇文章介绍本框架的原理。 #include<iostream> using namespace std;…

PHPCMS v9城市分站插件

PHPCMS自带的有多站点功能&#xff0c;但是用过的朋友都知道&#xff0c;自带的多站点功能有很多的不方便之处&#xff0c;例如站点栏目没法公用&#xff0c;每个站点都需要创建模型、每个站点都需要单独添加内容&#xff0c;还有站点必须静态化。如果你内容很多这些功能当然无…

虚函数和纯虚函数

虚函数 被virtual修饰的成员函数称为虚函数 定义一个函数为虚函数&#xff0c;是为了使用基类指针调用子类函数。虚函数&#xff0c;不代表函数不被实现。只有纯虚函数才不被实现&#xff0c;纯虚函数定义了一个接口&#xff0c;起到规范的作用。 #include <iostream>…

【AXIS】AXI-Stream FIFO设计实现(四)——异步时钟

前文介绍了几种同步时钟情况下的AXI Stream FIFO实现方式&#xff0c;一般来说&#xff0c;FIFO也需要承担异步时钟域模块间数据传输的功能&#xff0c;本文介绍异步AXIS FIFO的实现方式。 如前文所说&#xff0c;AXI-Stream FIFO十分类似于FWFT异步FIFO&#xff0c;推荐参考前…

B201-SpringBoot整合Shiro

目录 ShiroShiro核心组件SpringBoot整合Shiro1.创建新SpringBoot项目和导包2.自定义Shiro过滤器Realm3.配置类ShiroConfig编写认证和授权规则案例&#xff1a;案例思路改造ShiroConfigAccountController配置视图解析器templates下新建3个页面启动测试 登录认证设置自定义登录页…

Go的数据结构与实现【Graph】

介绍 图是网络结构的表示。现实世界中有大量图谱示例&#xff0c;互联网和社交图谱就是经典示例。图基本上是一组由边连接的节点。 实现 实现思路 图形数据结构将实现这些方法&#xff1a; AddNode()&#xff1a;添加一个节点到图里 AddEdge()&#xff1a;添加一条边到图里…

【C++庖丁解牛】自平衡二叉搜索树--AVL树

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1 AVL树的概念2. AVL…

探索未来的视觉智能:AI视频分析系统的崭新时代

随着人工智能技术的飞速发展&#xff0c;AI视频分析系统正逐渐成为各行业的关注焦点。这些系统不仅可以帮助安防领域实现更智能化的监控&#xff0c;还能在零售、交通、医疗等领域发挥重要作用。本文将深入探讨AI视频分析系统的崭新时代&#xff0c;揭示其未来发展的无限可能。…

曼哈顿距离转化为切比雪夫距离

目录 1 介绍2 训练3 参考 1 介绍 本专题介绍曼哈顿距离如何转化为切比雪夫距离。 A点 ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​)和B点 ( x 2 , y 2 ) (x_2,y_2) (x2​,y2​)的曼哈顿距离定义为它们的坐标差绝对值之和&#xff0c;即 ∣ x 1 − x 2 ∣ ∣ y 1 − y 2 ∣ |x_1-x_…

2-HDFS常用命令及上传下载流程

HDFS NameNode 安全模式(safemode) 当NameNode被重启的时候&#xff0c;自动进入安全模式 在安全模式中&#xff0c;NameNode首先会触发edits_inprogress文件的滚动。滚动完成之后&#xff0c;更新fsimage文件 更新完成之后&#xff0c;NameNode会将fsimage文件中的元数据加…

利用python做模拟数据(测试数据),连接数据库和服务器接口,涉及雪花id服务

import datetime import jsonimport pymysql import requests import snowflake.client from faker import Faker#cmd启动snowflake服务&#xff1a; #snowflake_start_server --addresslocalhost --port8910 --dc1 --worker1 def create_testers():# 创建一个中文Faker实例fak…

Python 判断当前操作系统的几种方法

本文介绍 Python 判断操作系统的3种方法。以下的方法将分为这几部分&#xff1a; Python os.namePython sys.platformPython platform.system() Python os.name Python 判断操作系统的方法可以使用 os.name&#xff0c;这里以 Python 3 为例&#xff0c;os.name 会返回 posi…

基于java+SpringBoot+Vue的网上书城管理系统设计与实现

基于javaSpringBootVue的网上书城管理系统设计与实现 开发语言: Java 数据库: MySQL技术: SpringBoot MyBatis工具: IDEA/Eclipse、Navicat、Maven 系统展示 前台展示 后台展示 系统简介 整体功能包含&#xff1a; 网上书城管理系统是一个基于互联网的在线购书平台&#…

文献学习-23-MRM:用于遗传学医学图像预训练的掩码关系建模

MRM: Masked Relation Modeling for Medical Image Pre-Training with Genetics Authors: Qiushi Yang, Wuyang Li, Baopu Li, Yixuan Yuan Source: ICCV 2023 Abstract: 关于自动多模态医疗诊断的 ODERN 深度学习技术依赖于大量的专家注释&#xff0c;这既耗时又令人望而却…

【Spring MVC】快速学习使用Spring MVC的注解及三层架构

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【Spring MVC】快速学习使用Spring MVC的注解及三层架构 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 Spring Web MVC一: 什么是Spring Web MVC&#xff1…

何时应用 RAG 与微调

充分发挥 LLM 的潜力需要在检索增强生成&#xff08;RAG&#xff09;和微调之间选择正确的技术。 让我们来看看何时对 LLM、较小的模型和预训练模型使用 RAG 与微调。我们将介绍&#xff1a; LLM 和 RAG 的简要背景RAG 相对于微调 LLM 的优势何时针对不同模型大小对 RAG 进行…

python 贪吃蛇

main.py #!/usr/bin/env python3 # -*- coding: utf-8 -*-import pygame # 导入pygame模块from setting import Setting import startmain as sm from pygame.sprite import Groupdef InitGame():print("InitGame")pygame.init() #初始化pygameai_settings Se…

【图轮】【 最小生成树】【 并集查找】1489. 找到最小生成树里的关键边和伪关键边

本文涉及知识点 图轮 最小生成树 并集查找 关键边 1489. 找到最小生成树里的关键边和伪关键边 给你一个 n 个点的带权无向连通图&#xff0c;节点编号为 0 到 n-1 &#xff0c;同时还有一个数组 edges &#xff0c;其中 edges[i] [fromi, toi, weighti] 表示在 fromi 和 to…

书生·浦语全链路开源开放体系 第二期

文章目录 大模型背景大模型开发流程InternLM 2.0SFT与RLHFInternLM2主要亮点 书生浦语全链路开源开放体系数据-书生万卷InternLM-Train微调 XTuner评测工具 OpenCompass部署 LMDeploy智能体 Lagent智能体工具箱 AgentLego 大模型背景 专用模型&#xff1a;针对特定的任务&…

【Web】NSSCTF Round#20 Basic 个人wp

目录 前言 真亦假&#xff0c;假亦真 CSDN_To_PDF V1.2 前言 感谢17&#x1f474;没让我爆零 真亦假&#xff0c;假亦真 直接getshell不行&#xff0c;那就一波信息搜集呗&#xff0c;先开dirsearch扫一下 扫的过程中先试试常规的robots.txt,www.zip,shell.phps,.git,.sv…