【C++】特殊类的设计与类型转换

文章目录

  • 1. 特殊类的设计
    • 1.1 不能被拷贝的类
    • 1.2 只能在堆上创建对象的类
    • 1.3 只能在栈上创建对象的类
    • 1.4 不能被继承的类
    • 1.5 只能创建一个对象的类(单列模式)
  • 2. 类型转换
    • 2.1 C/C++的类型转换
    • 2.2 C++规定的四种类型转换
      • 2.2.1 static_cast
      • 2.2.2 reinterpret_cast
      • 2.2.3 const_cast
      • 2.2.4 dynamic_cast

在这里插入图片描述

1. 特殊类的设计

1.1 不能被拷贝的类

请设计一个类,不能被拷贝

拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可

在C++98中,将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可

在这里插入图片描述
原因:

  1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不能禁止拷贝了
  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了

在这里插入图片描述
C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。

此时只要调用到这两个函数就会报错。
在这里插入图片描述

1.2 只能在堆上创建对象的类

实现方式:

  1. 类的构造函数私有,拷贝构造声明成私有(或者delete)。防止别人调用拷贝构造在栈上生成对象。
  2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建

在这里插入图片描述

class A
{
public://设置为静态可直接使用类名访问,无需对象调用static A* Create(int a){return new A(a);}private:A(int a = 0):_a(a){}A(const A& a):_a(a._a){}int _a;
};int main()
{//不能在栈上创建对象//A aa1;//A aa2(10);A* aa3 = A::Create(20);//调用规定函数在堆上创建对象//A aa4(*aa3);//若不禁掉拷贝构造,仍可在栈上创建对象return 0;

1.3 只能在栈上创建对象的类

设计一个类,不得使用new创建对象

方法一:将构造函数私有化,然后设计静态方法创建对象返回,同时将拷贝构造禁掉,使其使用移动构造。

在这里插入图片描述

很明显,方法一并不能封的很死。

方法二:将构造函数私有化,然后设计静态方法创建对象返回,同时将operator new 与operator delete 禁掉,使其无法使用new;并且将拷贝构造禁掉,创建对象时使用移动构造

在这里插入图片描述
这种方法也不能完全封死,依旧有隐患。
所以只要把拷贝构造或者移动构造暴露,就会有隐患,使用时按需选择。

1.4 不能被继承的类

C++98中构造函数私有化,派生类中调不到基类的构造函数,则无法继承。

在这里插入图片描述

C++11中,使用final关键字,final修饰类,表示该类不能被继承。

在这里插入图片描述

1.5 只能创建一个对象的类(单列模式)

  • 单例模式:一个类只能创建一个对象,即单例模式。该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享
  • 用处:比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

单例模式有两种实现模式:

  • 饿汉模式:不管你将来用不用,程序启动时就创建一个唯一的实例对象。

在这里插入图片描述
注意:static类型的对象不在对象里面,在静态区,它仅受类域的限制,因此不会引发无穷递归

为了防止使用拷贝构造和赋值重载创建多个对象,所以也应该封一下。

在这里插入图片描述
到此就完整了

class InfoManager
{
public:static InfoManager& GetInstance(){return _instance; //每次返回的都是同一个}private:InfoManager()  //将构造函数私有{cout << "InfoManager()" << endl;}InfoManager(const InfoManager& p) = delete;InfoManager& operator=(const InfoManager& p) = delete;private:string _ip = "192.168.2.4";int _potr = 80;//...static InfoManager _instance; //声明一个在静态区的对象,该对象受类域的限制
};InfoManager InfoManager::_instance; //创建对象int main()
{InfoManager::GetInstance();//InfoManager copy(InfoManager::GetInstance());
}

如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避免资源竞争,提高响应速度更好。

  • 懒汉模式:第一次使用实例对象时,创建对象

对于该模式来说,它跟饿汉模式差不多,只不过它在第一次调用GetInstance时创建对象,所以我们可以将其设置为指针。
在这里插入图片描述

还有一种更简单的方式(C++11后推荐使用):

在这里插入图片描述

注意:成员函数也不在对象里面,在代码段

如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。

2. 类型转换

2.1 C/C++的类型转换

在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不一致时,就需要发生类型转化。

C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换

  • 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败(整型之间、整型和浮点数之间都可以转换)
  • 显式类型转化:需要用户自己处理
  1. 内置类型之间可以转
void Test()
{int i = 10;// 隐式类型转换double d = i;printf("%d, %.1f\n", i, d);int* p = &i;// 显示的强制类型转换int address = (int)p;printf("%x, %d\n", p, address);
}
  1. 内置类型和自定义类型之间不可以直接转,但可以依靠构造函数、运算符重载转换

内置类型->自定义类型,依靠构造函数转换

class A
{
public:A(int a):_a(a),_b(a){}A(int a,int b):_a(a),_b(b){}
private:int _a;int _b;
};int main()
{A aa1 = 1;//调单参数的构造转换A aa2 = { 10,20 };//调多参数的构造转换
}

自定义类型->内置类型,使用 operator + 类型,没有返回值

在这里插入图片描述

  1. 自定义类型和自定义类型之间

依靠构造函数,实现自定义类型之间的转换

在这里插入图片描述

2.2 C++规定的四种类型转换

标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符,目的就是规范转换,使转换更加清晰。

2.2.1 static_cast

static_cast对应的是隐式类型转换

在这里插入图片描述

2.2.2 reinterpret_cast

reinterpret_cast用于将一种类型转换为另一种不同的类型,对应强制类型转换

在这里插入图片描述

2.2.3 const_cast

const_cast最常用的用途就是删除变量的const属性,方便赋值(对应强制类型转换中有风险的去掉const属性

但是下面的代码中我们发行并没有修改掉变量a,这是由于编译器的优化。

在这里插入图片描述
这里我们可以加上volatile关键字。

在这里插入图片描述

volatile作用:不让编译器优化,规规矩矩的执行,达到稳定访问内存的目的(volatile忽略编译器的优化,保持内存可见性)

2.2.4 dynamic_cast

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(运行时转换)

  • 向上转型:子类对象指针/引用->父类指针/引用(不需要转换,切片)
  • 向下转型:父类对象指针/引用->子类指针/引用(使用强制类型转换是不安全的,可能会越界访问;用dynamic_cast转换是安全的)

dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0。(如果父类指针或引用指向子类,此时转换为子类是安全的;如果父类指针或引用指向父类,此时转换为子类是不安全的,会越界)
在这里插入图片描述

dynamic_cast只能用于父类含有虚函数的类(因为其会在虚表中添加一些标识,以识别指向父类还是子类)

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

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

相关文章

【吊打面试官系列-Elasticsearch面试题】对于 GC 方面,在使用 Elasticsearch 时要注意什么?

大家好&#xff0c;我是锋哥。今天分享关于 【对于 GC 方面&#xff0c;在使用 Elasticsearch 时要注意什么&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 对于 GC 方面&#xff0c;在使用 Elasticsearch 时要注意什么&#xff1f; 1、SEE 2、倒排词典的索引需…

vue3使用pnpm运行项目但是运行不起来

运行项目的时候发现根本运行不起来了 尝试过创建.npmr文件 删除node_modules重新下 但是都出现问题了 创建.npmr&#xff1a;不管用 删除node_modules重新下&#xff1a;文字编译乱码&#xff0c;utf-8可能解析处理问题 最后解决方法&#xff1a; 重新创建项目&#xff0…

网络科技公司官网电商软件开发小程序网站pbootcms模板带手机端

免费授权可商用网站模板 PC端移动端后台测试数据 所有页面均都能完全自定义标题/关键词/描述&#xff0c;PHP程序&#xff0c;安全、稳定、快速&#xff0c;响应式同一个后台&#xff0c;数据即时同步&#xff0c;简单适用&#xff0c;附带测试数据&#xff01;&#xff01;

物流仓库安全视频智能管理方案:构建全方位、高效能的防护体系

一、背景分析 随着物流行业的快速发展和仓储需求的日益增长&#xff0c;仓库安全成为企业运营中不可忽视的重要环节。传统的人工监控方式不仅效率低下&#xff0c;且难以做到全天候、无死角覆盖&#xff0c;给仓库资产和人员安全带来潜在风险。因此&#xff0c;引入仓库安全视…

了解细胞外基质:它是啥?有啥作用?

了解细胞外基质&#xff1a;它是啥&#xff1f;有啥作用&#xff1f; 大家好&#xff0c;今天我们来阅读这篇Biofabrication methods for reconstructing extracellular matrix mimetics发表于《Bioactive Materials》上的文章。细胞外基质在人体中起着至关重要的作用&#xff…

同城门户同城分类信息网站源码discuz插件+pc端+小程序端+49款插件

同城分类信息 同城好店 同城合伙人 同城招聘 同城卡 同城活动 同城优惠抢购 同城商城 同城头条 同城抽奖 同城拼团 同城砍价 同城电话本 同城认证 同城签到 同城拼车 同城红包 同城子站点 同城相亲 同城交友 同城小程序 比较流行的同城信息门户网站源码&#xff0c;基于dz&…

【计算机网络】网络基础概念

目录 计算机网络发展 协议 协议分层 OSI 七层模型 TCP/IP 五层&#xff08;四层&#xff09;模型 究竟什么是协议&#xff1f; 网络与操作系统的关系 网络传输基本流程 局域网网络传输流程 认识 MAC 地址 局域网&#xff08;以太网为例&#xff09;通信原理 数据包…

【前端设计方案】H5 图片懒加载 SDK

实现思路 定义<img srcloading.png data-srcxxx.png/>页面滚动&#xff0c;图片露出时&#xff0c;将 data-src 赋值给 src 注意事项&#xff1a;滚动要节流 技术要点 获取图片的位置 elem.getBoundingClientRect() 图片 top < window.innerHeight 时&#xff0c;图片…

Install pytorch 使用 torch 的例子

如果不知道怎么开始和安装软件 从这里开始 如果需要GPU版本&#xff0c;请选择CUDA&#xff0c;而不是CPU PyTorchhttps://pytorch.org/ Python 3.8.13 | packaged by conda-forge | (default, Mar 25 2022, 06:04:10) [GCC 10.3.0] on linux Type "help", &quo…

opencv 深度图视差图可视化案例

参考:https://www.cnblogs.com/zyly/p/9373991.html(图片这里面下载的) https://blog.csdn.net/He3he3he/article/details/101053457 原理 双目摄像头 视差公式: 三角形对应推算 深度距离转换: 这里d是视差Disparity 代码 下面两种计算视差方法: import os impor…

计算机毕业设计Hadoop+Hive居民用电量分析 居民用电量可视化 电量爬虫 机器学习 深度学习 大数据毕业设计 Spark

《Hadoop居民用电量分析》开题报告 一、研究背景与意义 能源问题在全球范围内一直是热点议题&#xff0c;尤其是随着居民生活水平的提高和城市化进程的加快&#xff0c;居民用电量急剧增长&#xff0c;对电力系统的稳定运行和能源管理提出了更高要求。如何科学合理地管理和分…

T9打卡学习笔记

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 import tensorflow as tfgpus tf.config.list_physical_devices("GPU")if gpus:tf.config.experimental.set_memory_growth(gpus[0], True) #设置…

红黑树的插入

文章目录 3.红黑树3.1概念3.2 性质3.3 RBTree的实现3.3.1 insert的框架3.3.2 insert的处理3.3.3 中序遍历3.3.4检查是否平衡和获取树的高度 3.4完整代码 3.红黑树 3.1概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xf…

07一阶电路和二阶电路的时域分析

一阶电路和二阶电路的时域分析 时域分析、频域分析、复频域分析本应该在信号与系统&#xff0c;或者数字信号处理这一章节里面进行处理的。 但在电路理论中也有这些知识&#xff0c;那就要好好掌握一下&#xff0c;打个底。详细细致的部分放到信号与系统里面去掌握

【单片机开发软件】使用VSCode开发STM32环境搭建

&#x1f48c; 所属专栏&#xff1a;【单片机开发软件技巧】 &#x1f600; 作  者&#xff1a; 于晓超 &#x1f680; 个人简介&#xff1a;嵌入式工程师&#xff0c;专注嵌入式领域基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大家&#xff1…

Java Web —— 第四天(HTTP协议,Tomcat)

HTTP-概述 概念:Hyper Text Transfer Protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则 特点: 1. 基于TCP协议:面向连接&#xff0c;安全 2.基于请求-响应模型的:一次请求对应一次响应 3. HTTP协议是无状态的协议: 对于事务处理没有…

ASUS/华硕魔霸新锐2020 G512L系列 原厂win10系统 工厂文件 带F12 ASUS Recovery恢复

华硕工厂文件恢复系统 &#xff0c;安装结束后带隐藏分区&#xff0c;一键恢复&#xff0c;以及机器所有驱动软件。 系统版本&#xff1a;windows10 原厂系统下载网址&#xff1a;http://www.bioxt.cn 需准备一个20G以上u盘进行恢复 请注意&#xff1a;仅支持以上型号专用…

【多线程】CAS、ABA问题详解

一、什么是 CAS CAS&#xff1a;全称 Compare and swap&#xff0c;字⾯意思&#xff1a;⽐较并交换 比较内存和 CPU 中的内容&#xff0c;如果发现相同&#xff0c;就进行交换 交换的是内存和另一个寄存器的内容 一个内存的数据和两个寄存器中的数据进行操作&#xff08;寄…

CSS 多按钮根据半圆弧度排列

需求 多个按钮根据弧度&#xff0c;延边均匀排列。 实现 HTML 分两级&#xff1b;第一级&#xff0c;外层定义按钮的 compose-container 宽度&#xff1b;第二级&#xff0c;按钮集合&#xff0c;使用方法 styleBtn(index)&#xff0c;根据索引计算&#xff1b; <div c…

青岛实训 8月9号 day25

mysql下载路径&#xff1a; MySQL :: MySQL Community Downloads [root2 ~]# vim py001.pya3b4print(ab)print(a**2b**2)[root2 ~]# python py001.py 725[root2 ~]# python3>>> import random>>> random<module random from /usr/lib64/python3.6/random…