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

news2024/11/26 0:42:27

文章目录

  • 1. 特殊类的设计
    • 单例模式
      • 饿汉模式
        • 具体代码
      • 懒汉模式
        • 具体代码
      • 懒汉模式和饿汉模式的优缺点
  • 2. C++的类型转换
    • C语言的类型转换
    • C++的类型转换
      • static_cast
      • reinterpret_cast
      • const_cast
      • dynamic_cast

1. 特殊类的设计

单例模式

设计模式是 被反复使用 多数人知晓 经过分类的、代码设计经验的总结


单例模式:
一个类只能创建一个对象 即单例模式,该模式可以保证系统中该类只有一个实例

单例模式分为饿汉模式和懒汉模式

饿汉模式

一开始就创建对象(main函数之前)

假设想要vector数组全局只有一份
所以进行限制,使之不能随意创建对象 即将构造函数私有化

若想要创建对象,则通过公有的成员函数getinstallce创建
为了保证每次获取的都是同一个对象,就定义了一个静态的类类型的指针 _p
而静态的成员变量,需要在类外面初始化


在定义静态成员变量时 创建对象


此时也可添加add增加和print打印的功能

定义私有的string数组 _v,使用其push_back 添加数据str,并使记录数字+1


使用print函数打印数据


由于getinstallce函数返回值是一个指针,所以需要使用->去访问add或者print函数


还可以通过设置锁进行多线程间的安全访问

设置私有锁


由于getinstallce函数返回值是一个静态的指针,所以无论是线程t1还是线程t2都可以访问到该函数
并通过该函数调用add或者 print函数
使用to_string 将任意类型转化为string

具体代码

饿汉模式
class stu
{
public:
	static stu* getinstallce()
	{
		return _p;
	}
	void add(const string& str)
	{
		_mtx.lock();//加锁
		_v.push_back(str);
		++_x;
		_mtx.unlock();//解锁
	}
	void print()
	{
		_mtx.lock();//加锁
		for (auto& e : _v)
		{
			cout << e << " ";
			cout << endl;
		}
		_mtx.unlock();//解锁
	}
private:
	//限制类外不能随意创建对象
	//构造函数私有化
	stu(int x=0)
		:_x(x)
	{
	}
private:
	mutex _mtx;
	int _x=0;
	vector<string>_v;
	static stu* _p;
};
//static成员变量在类外定义
stu* stu:: _p = new stu;


int main()
{
	int n = 10;
	thread t1([n]() {
		for (int i = 0; i < n; i++)
		{
			stu::getinstallce()->add("t1线程:"+to_string(i));
		}
		});
	thread t2([n]() {
		for (int i = 0; i < n; i++)
		{
			stu::getinstallce()->add("t2线程:" + to_string(2*i));
		}
		});
	t1.join();
	t2.join();
	stu::getinstallce()->print();
}
int main()
{
	stu::getinstallce()->add("张三");
	stu::getinstallce()->add("李四");
	stu::getinstallce()->print();//打印
	return 0;
}

懒汉模式

第一次访问实例对象时创建(第一次调用getinstallce函数时创建)

在饿汉模式的代码的基础上进行改造


在定义静态成员变量时设置为空


若_p指针为空,在创建对象,并返回
在调用getinstallce函数时才创建对象


虽然看似没有问题,但是在多线程下还存在线程安全的问题

定义一个静态锁,用于保护getinstallce函数中的实例对象


在初始化时,是不需要显示给值的


每次获取对象都要加锁解锁,但实际上只需要保证第一次即可


这样的写法依旧是不行的,当两个线程t1 t2同时进入if循环中,
当线程t1 new后解锁,线程t2获取锁,继续new,就会造成覆盖 丢失数据


所以采用双检查加锁的方式

具体代码

//懒汉模式
class stu
{
public:
	static stu* getinstallce()
	{
		//双检查加锁
		if (_p == nullptr)
		{
			_imtx.lock();//加锁
			if (_p == nullptr)
			{
				_p = new stu;
			}
			_imtx.unlock();//解锁
		}
		return _p;
	}
	void add(const string& str)
	{
		_mtx.lock();//加锁
		_v.push_back(str);
		++_x;
		_mtx.unlock();//解锁
	}
	void print()
	{
		_mtx.lock();//加锁
		for (auto& e : _v)
		{
			cout << e << " ";
			cout << endl;
		}
		_mtx.unlock();//解锁
	}
	//特殊情况下释放单例对象
	static void delinstance()
	{
		_imtx.lock();
		if (_p)
		{
			delete _p;
			_p = nullptr;
		}
		_imtx.unlock();
	}
private:
	//限制类外不能随意创建对象
	//构造函数私有化
	stu(int x = 0)
		:_x(x)
	{
	}
	
	//防拷贝
	stu(const stu& s) = delete;
	stu& operator=(const stu& s) = delete;

private:
	static mutex _imtx;
	mutex _mtx;
	int _x = 0;
	vector<string>_v;
	static stu* _p;
};
//static成员变量在类外定义	 
stu* stu::_p = nullptr;
//将静态锁在类外初始化
mutex stu::_imtx;


懒汉模式和饿汉模式的优缺点

饿汉模式的缺点:
1.若单例对象初始化很慢(如初始化动作多),main函数之前就要申请,暂时不需要使用 就会造成 占用资源、程序启动会变慢受影响
2.若两个单例都是饿汉,并且有依赖关系,要求单例1先创建,单例2再创建,饿汉无法控制顺序,懒汉才可以

(两者是懒汉,则都是使用 成员的静态指针进行new创建对象的,谁先new是控制不住的
而两者都是饿汉,则都是在getinstallce函数中创建对象,
可以控制单例1先在getinstallce函数中创建对象,再让单例2在getinstallce函数中创建对象)

饿汉模式的优点:
优点只有一个,简单

懒汉完美的解决了上面饿汉的问题,变得相对更复杂一点

2. C++的类型转换

C语言的类型转换

C语言有隐式类型转换 和显式类型转换

i为int类型,想要转化为double类型,就需要进行隐式类型转换
即 先将i赋值给一个double类型的临时变量,再通过临时变量赋值给d

p作为一个指针,i作为一个int类型变量,虽然都是4个字节,但是意义不同,所以不能互相转,只能进行显式类型转换
即 将int*类型的指针强转为int类型

C++的类型转换

隐式类型转化 存在精确度丢失的问题
显式类型转化 存在代码不够清晰的问题
所以C++提出了自己的类型转化风格,引入四种强制类型转换操作符
static_cast reinterpret_cast const_cast dynamic_cast

static_cast

static_cast对应c语言中的隐式类型转换
两个变量 是相关的类型 (double和int)

把int类型转化为double类型

reinterpret_cast

reinterpret_cast对应C语言的显式强制类型转换
两个变量 是不相关的类型 (int和int*)

把int类型转化为 int*类型

const_cast

去掉const属性

a为const int类型,转化为&a后,类型为const int*
通过const_cast后,b等待类型为int*类型,可以对b解引用修改
a的值依旧为10,不会被修改
而b的值为5

因为编译器进行优化,把a的值放入寄存器中,而b所修改实际上是寄存器的a值而不是内存中的a值,所以a依旧为10

dynamic_cast

C++独有的

dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
父类作为上 ,子类作为下


向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)


父类对象是无法转换为子类对象的


向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的,直接强制转换是不安全的)

A作为父类,B作为子类
所以将p强制转换为B*,存在风险,如果B有自己的成员,用指针可以访问这些成员,但这个访问就强制越界了,多开的一部分空间不属于你的


dynamic_cast 会先进行检查,若指向父类对象,则转换失败,若指向子类对象,则转换成功

注意:
dynamic_cast只能用于父类含有虚函数的类

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

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

相关文章

【Docker】Docker中容器之间通信方式

文章目录 1. Docker容器之间通信的主要方式1.1 通过容器ip访问1.2. 通过宿主机的ip:port访问1.3. 通过link建立连接&#xff08;官方不推荐使用&#xff09;1.4. 通过 User-defined networks&#xff08;推荐&#xff09; 2. 参考资料 1. Docker容器之间通信的主要方式 1.1 通…

OpenCV图像处理-视频分割静态背景-MOG/MOG2/GMG

视频分割背景 1.概念介绍2. 函数介绍MOG算法MOG2算法GMG算法 原视频获取链接 1.概念介绍 视频背景扣除原理&#xff1a;视频是一组连续的帧&#xff08;一幅幅图组成&#xff09;&#xff0c;帧与帧之间关系密切(GOP/group of picture)&#xff0c;在GOP中&#xff0c;背景几乎…

前端面试题汇总大全!

文章目录 前端面试题汇总大全&#xff08;含答案超详细&#xff09;-- 持续更新一、HTML 篇1.xhtml和html有什么区别2.行内元素有哪些&#xff1f;块级元素有哪些&#xff1f; 空(void)元素有那些&#xff1f;行内元素和块级元素有什么区别3. 简述一下你对 HTML 语义化的理解&a…

sql进阶 之case表达式

case表达式 CASE表达式是SQL里非常重要而且使用起来非常便利的技术&#xff0c;我们应该学会用它来描述条件分支。本节将通过行列转换、已有数据重分组&#xff08;分类&#xff09;、与约束的结合使用、针对聚合结果的条件分支等例题&#xff0c;来介绍CASE表达式的用法。标红…

在 3dsmax 中创建电影场景

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 有时&#xff0c;通过简单的图像和简单的技术&#xff0c;我们可以创建有效的输出。在本教程中&#xff0c;您将学习如何在 3ds max 中使用三个简单图像创建电影场景。 步骤-1 让我们在 photoshop 中为场…

Java 二维码生成解析

生成二维码需要两个jar包 Download core JAR 3.5.1 ➔ With all dependencies! Download javase JAR 3.5.1 ➔ With all dependencies! 将下载后的jar包添加项目依赖 import com.google.zxing.*; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.googl…

具身智能,是机器人的“冷饭热炒”吗?

大模型正如火如荼&#xff0c;下一个AI风口就来了。 如果你关注2023世界人工智能大会等行业峰会&#xff0c;以及英伟达、微软、谷歌、特斯拉和国內科技大厂的最新发布会&#xff0c;除了“大模型”&#xff0c;应该会听到另一个高频词——具身智能。 所谓具身智能Embodied AI …

【运维】 第05课:Curl 命令最常见使用方式及案例

本课时我们主要了解 Curl 命令的使用和常见案例。在学习本课时的内容之前&#xff0c;你需要先了解 HTTP 的请求过程&#xff0c;以及 Linux 操作系统的基础知识。 首先&#xff0c;我们先来介绍一下 Curl &#xff0c;Curl 是一个Linux命令行中的工具&#xff0c;它模拟客户端…

JAVA解析EXCEL(JExcelAPI,POI,EasyExcel)

前言 文章目录 前言JExcelAPIDemo POIHSSFWorkBookXSSFWorkBookDemo SXSSFWorkBookDemo XSSFReaderDemo EasyExcelDemo demo代码&#xff1a;https://github.com/RwTo/excel-demo JAVA解析Excel 一般有三种方式 JExcelAPI POI EasyExcel JExcelAPI 官网&#xff1a;https://je…

centos安装psql客户端

前言&#xff1a;postgresql数据库采用docker部署&#xff0c;想在宿主机测试访问或数据库备份&#xff0c;则需要安装postgresql客户端&#xff0c;即psql命令 环境&#xff1a;centos7&#xff0c;x86&#xff0c;yum 下面以 postgresql-11 为例 安装镜像 yum install htt…

探索 APK 文件的内部:了解 Android 应用程序的组织结构

I. 什么是 APK 文件 APK (Android application package) 是构建和发布 Android 应用程序的关键组成部分&#xff0c;APK 文件是应用程序的打包格式&#xff0c;它将应用程序的代码、资源和清单信息组合在一起&#xff0c;以便在设备上进行安装和运行。 简称 ”安装包“&#…

Linux系统安装部署Jenkins详细教程(图文讲解)

前言&#xff1a;最近需要使用Jenkins部署项目&#xff0c;所以想出一篇关于如何使用Linux系统安装部署Jenkins的相关教程&#xff0c;整体部署过程还是挺顺利的&#xff0c;特此分享一下&#xff01; 目录 一、安装JDK11和Tomcat11 二、准备Jenkins安装包 三、部署Jenkins…

云端环境跑通BaseLine

云端环境跑通BaseLine 一、实验流程实践 1.报名 报名日期&#xff1a;2023年7月17日&#xff0c;参与AI夏令营第一期 彳 z h i 亍 c h u &#xff0c;都为第四声 \overset{zhi}{彳}\overset{chu}{亍}&#xff0c;都为第四声 彳zhi亍chu&#xff0c;都为第四声 怎么报名的&a…

C++OpenCV(7):图像形态学基础操作

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 &#x1f506; OpenCV项目地址及源代码&#xff1a;点击这里 文章目录 膨胀与腐蚀形态学基础 膨胀与腐蚀 膨胀与腐蚀是数学形态学在图像处理中最基础的操作。 膨胀操作是取每个位置领域内最大值&#xff0…

linux系统编程--线程同步

1.同步概念 所谓同步&#xff0c;即同时起步&#xff0c;协调一致。不同的对象&#xff0c;对“同步”的理解方式略有不同。如&#xff0c;设备同步&#xff0c;是指在两个设备之间规定一个共同的时间参考&#xff1b;数据库同步&#xff0c;是指让两个或多个数据库内容保持一致…

13、ffmpeg使用nvidia显卡对OAK深度相机进行解码和编码

基本思想&#xff1a;简单使用nvidia的硬件解码进行oak相机的编码和解码学习 一、在本机rtx3060配置好显卡驱动和cuda之后进行下面操作50、ubuntu18.04&20.04CUDA11.1cudnn11.3TensorRT7.2/8.6Deepsteam5.1vulkan环境搭建和YOLO5部署_ubuntu18.04安装vulkan_sxj731533730的…

C# 右键菜单 contextMenuStrip

最近需要使用到C#的右键菜单contextMenuStrip控件。 这里记录一下。 首先在工具箱中找到contextMenuStrip控件。将他拖到你的窗体中&#xff0c;如下图所示&#xff1a; 默认名称为&#xff1a;contextMenuStrip1. 然后将你需要使用右键属性的控件和contextMenuStrip1绑定起…

Mac上安装sshfs

目录 写在前面安装使用参考完 写在前面 1、本文内容 Mac上安装sshfs 2、平台 mac 3、转载请注明出处&#xff1a; https://blog.csdn.net/qq_41102371/article/details/130156287 安装 参考&#xff1a;https://ports.macports.org/port/sshfs/ 通过port安装 点击啊insta…

IC设计从业者必备的宝藏网站!

对于IC设计从业者而言&#xff0c;获取准确的学习资源&#xff0c;行业资讯直观重要&#xff0c;今日我们推荐ic行业专业的宝藏网站&#xff0c;希望对从业者有所帮助。 01-找开源项目的网站 GitHub除了Git代码仓库托管及基本的 Web管理界面以外&#xff0c;还提供了订阅、讨论…

WebClient,HTTP Interface远程调用阿里云API

HTTP Interface Spring 允许我们通过定义接口的方式&#xff0c;给任意位置发送 http 请求&#xff0c;实现远程调用&#xff0c;可以用来简化 HTTP 远程访问。需要webflux场景才可 <dependency><groupId>org.springframework.boot</groupId><artifactId&…