C++ | 深入理解C++中的特殊类设计和单例模式(懒汉模式、饿汉模式)
目录
特殊类设计和单例模式
1、不可拷贝类
2、只能在堆上创建对象的类
3、只能在栈上创建对象的类
4、不可继承的类
5、单例模式(懒汉模式、饿汉模式)
特殊类设计和单例模式
在C++编程中,类的设计往往需要满足特定的需求和约束。特殊类设计模式提供了一种方法来实现这些需求,确保类的使用既安全又高效。本文将探讨几种常见的特殊类设计方式,包括不可拷贝类、只能在堆上创建对象的类、只能在栈上创建对象的类、不可继承的类以及单例模式。
1、不可拷贝类
在某些情况下,我们可能希望一个类的对象不能被拷贝。这可以通过以下两种方式实现:
C++98方式
在C++98中,我们可以通过只声明拷贝构造函数和赋值运算符,并将它们设置为私有成员来实现。这样,即使外部代码尝试拷贝对象,编译器也会因为访问权限问题而报错。
// 不可拷贝类
// 将拷贝构造和赋值运算符重载delete即可
class uncopy
{
private:int _a;uncopy(const uncopy& uc);uncopy& operator=(const uncopy& uc);
public:uncopy(int a = 0):_a(a){}};
C++11方式
C++11引入了delete关键字,可以直接在类声明中删除默认的拷贝构造函数和赋值运算符,使得编译器在尝试使用这些函数时直接报错。
// 不可拷贝类
// 将拷贝构造和赋值运算符重载delete即可
class uncopy
{
private:int _a;
public:uncopy(int a = 0):_a(a){}uncopy(const uncopy& uc) = delete;uncopy& operator=(const uncopy& uc) = delete;};
2、只能在堆上创建对象的类
有时,我们希望类的实例只能在堆上创建,这可以通过以下步骤实现:
- 将构造函数声明为私有
- 提供一个公共的静态成员函数,用于在堆上分配和初始化对象。
或者:
- 将析构函数声明为私有
- 提供公共的静态成员函数,用来调用析构函数销毁对象
// 只能在堆上创建对象的类
// 隐藏构造函数 开放静态获取接口 将拷贝构造函数delete
class Heap_only1
{
private:int _a;Heap_only1(int a = 0):_a(a){}Heap_only1(const Heap_only1& ho) = delete;
public:static Heap_only1* create_obj(int a){return new Heap_only1(a);}
};// 利用局部对象自动调用析构函数 隐藏析构函数 开放销毁接口 将拷贝构造函数delete
class Heap_only2
{
private:int _a;Heap_only2(const Heap_only2& ho) = delete;~Heap_only2(){}
public:Heap_only2(int a = 0):_a(a){}static bool delete_Heap_only(Heap_only2* p){if (p){delete p;p = nullptr;return true;}return false;}
};
3、只能在栈上创建对象的类
与只能在堆上创建对象的类相反,有时我们希望类的实例只能在栈上创建。这可以通过禁用operator new和operator delete来实现。
// 只能在栈上创建对象的类
// 将operator new和operator delete封住 提供传值返回接口获取栈上对象
// 但是 由于传值返回保留了拷贝构造函数 所以static拷贝构造无法完全封死
class stack_only
{
private:int _a;void* operator new(size_t size) = delete;void operator delete(void* p) = delete;stack_only(){}
public:static stack_only create_stack_only(){return stack_only();}
};
4、不可继承的类
在某些情况下,我们可能希望阻止其他类继承特定的类。这可以通过以下两种方式实现:
C++98方式
在C++98中,我们可以通过将构造函数声明为私有来实现,这样派生类就无法访问基类的构造函数。
class NonInherit {
private:NonInherit() {}
};
C++11方式
C++11引入了final关键字,可以直接在类声明中使用final来阻止继承。
class NonInherit final {// ...
};
5、单例模式(懒汉模式、饿汉模式)
单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。单例模式有两种实现方式:饿汉模式和懒汉模式。
饿汉模式
饿汉模式在程序启动时就创建实例,简单但可能导致启动延迟。
//单例模式
//饿汉模式
#include<iostream>
using namespace std;
class once1
{
private:once1(){}static once1* a;once1(const once1&) = delete;once1& operator=(const once1&) = delete;public:static once1* getObj(){return a;}
};
once1* once1::a = new once1;int main()
{once1* p1 = once1::getObj();cout << p1 << endl;return 0;
}
懒汉模式
懒汉模式在第一次使用时才创建实例,启动无负载。
[Warning] 以下为不考虑线程安全的版本
//懒汉模式
class once2
{
private:static once2* ret;once2(){}once2(const once2&) = delete;once2& operator=(const once2&) = delete;
public:static once2* getObj(){if (ret == nullptr){ret = new once2;}return ret;}
};
once2* once2::ret = nullptr;int main()
{once2* p2 = once2::getObj();cout << p2 << endl;return 0;
}
如果要求在程序退出时销毁单例对象,可以在once类中定义内部类,在内部类的析构函数中完成资源释放,程序结束时自动调用内部类的析构函数。
以懒汉模式为例:
//懒汉模式
class once2
{
private:static once2* ret;once2(){}once2(const once2&) = delete;once2& operator=(const once2&) = delete;class del{public:~del(){once2::delObj();}};static del D;
public:static once2* getObj(){if (ret == nullptr){ret = new once2;}return ret;}static void delObj(){if (ret){delete ret;ret = nullptr;cout << "delete[]" << endl;}}
};
once2* once2::ret = nullptr;
once2::del once2::D;int main()
{//once1* p1 = once1::getObj();//cout << p1 << endl;once2* p2 = once2::getObj();cout << p2 << endl;return 0;
}
相关文章:
C++ | 深入理解C++中的特殊类设计和单例模式(懒汉模式、饿汉模式)
目录 特殊类设计和单例模式 1、不可拷贝类 2、只能在堆上创建对象的类 3、只能在栈上创建对象的类 4、不可继承的类 5、单例模式(懒汉模式、饿汉模式) 特殊类设计和单例模式 在C编程中,类的设计往往需要满足特定的需求和约束。特殊类设计模式提供了一种方法来…...
Java设计模式之中介者模式
Java设计模式之中介者模式 在软件开发中,设计模式是解决常见问题的最佳实践。通过运用设计模式,我们可以提高代码的可维护性、可扩展性以及可读性。今天,我们将探讨一种非常重要的行为型设计模式——中介者模式(Mediator Pattern…...
实现父组件调用子组件方法时报错:[Vue warn]: Invalid vnode type when creating vnode: null.
使用uniapp实现父组件调用子组件方法时报错:[Vue warn]: Invalid vnode type when creating vnode: null. 实现代码如下: 子组件: <template><view><view class"toolsHeader"><view class"toolsTitl…...
Java面试八股之什么是消息队列
什么是消息队列 消息队列(Message Queue)是一种应用程序间通信(IPC)的形式,它允许进程将消息发送到另一个消息队列,接收端则可以在任何时刻从队列中取出这些消息进行处理。消息队列提供了一种异步处理、解…...
【kubernetes】k8s配置资源管理
一、ConfigMap资源配置 ConfigMap保存的是不需要加密配置的信息 ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被…...
高分六号卫星助力农业监测_卫星介绍_论文分享_数据获取
卫星遥感已经成为农业发展的重要支持工具。《“数据要素X”三年行动计划(2024-2026年)》指出,在现代农业交通运输、应急管理等领域鼓励探索利用遥感数据。为什么高分六号会经常应用于农业检测呢?本文将介绍高分六号卫星的农业检测特性、在农业应用中的优势、具体农业…...
【Linux网络】TCP协议
欢迎来到 破晓的历程的 博客 ⛺️不负时光,不负己✈️ 文章目录 引言1、TCP协议的特点2、确认应答机制3、超时重传机制4、TCP报头结构5、三次握手建立连接6、四次挥手断开连接总结 引言 TCP协议是传输层中非常重要的协议。本篇博客我们将从TCP头部信息、TCP状态转…...
Linux 基本指令讲解 上
linux 基本指令 clear 清屏 Alt Enter 全屏/退出全屏 pwd 显示当前用户所处路径 cd 改变目录 cd /root/mikecd … 返回上级目录cd - 返回最近所处的路径cd ~ 直接返回当前用户自己的家目 roor 中:/root普通用户中:/home/mike mkdir 创建一个文件夹(d) …...
深入了解指针(6)
文章目录 1.函数指针数组2.转移表3.回调函数 1.函数指针数组 存放函数指针的数组 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int add(int x, int y) {return x y; } int sub(int x, int y) {return x - y; }int main() {int (*p1)(int x, int y) add;int (…...
【Linux系列】known_hosts详解
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
MySQL4 多表查询 内连接
内连接 多表查询内连接 多表查询 数据准备 CREATE DATABASE db4; USE db4; -- 创建部门表 create table if not exists dept(deptno varchar(20) primary key , -- 部门号name varchar(20) -- 部门名字 );-- 创建员工表 create table if not exists emp(eid varchar(20) pr…...
力扣45:跳跃游戏2题解
题目链接: https://leetcode.cn/problems/jump-game-ii/description/?envTypestudy-plan-v2&envIdtop-100-liked 参考的代码随想录里面的题解: 题目 难度 中等,标的是中等难度,而且我之前做过这道题,但是我没写…...
产品经理-产品被同行抄袭如何处理(32)
在面试当中,如果被问到,产品被同行抄袭如何处理 竞争分析、战略决策。 1)对行业相关事件的关注度:如之前对腾讯抄袭事件的讨论,如果能结合“被抄袭”后的失败案例(例如联众)和反抄袭的成功案例(例如豆瓣&am…...
LDR6020在Type-C手机同时充电与USB2.0数据传输方案
随着科技的飞速发展,Type-C接口已成为智能手机等移动设备的主流充电和数据传输接口。为了满足用户对于高效充电与稳定数据传输的双重需求,乐得瑞科技推出的LDR6020芯片凭借其卓越的性能和丰富的功能,为Type-C手机提供了同时充电与USB2.0数据传…...
Python学习笔记(七)
""" 演示数据容器字典的定义 """# # 定义字典{key:value,key2:value2} 注意key不能是字典,value可以任意 # my_dict1 {"王力鸿": 99, "周杰轮": 88, "林俊节": 77}# #定义空字典 # my_dict2 {} # my…...
mysql中log
目录 MySQL 日志系统概述 日志类型 日志的作用和重要性 Mermaid图示 1. Undo Log 和 Redo Log 的协同工作图 2. Redo Log 确保持久性的流程图 Undo Log(回滚日志) 事务的原子性(Atomicity)保障 事务回滚机制 MVCC&#…...
iOS Object-C 创建类别(Category) 与使用
有时候使用系统给出类或者第三方的类,但是呢它们自带的属性和方法又太少,不够我们的业务使用,这时候就需要给“系统的类或者第三方类”创建一个类别(Category),把自己的想添加的属性和方法写进来. Category模式用于向已经存在的类添加方法从而达到扩展已有类的目的 一:创建Ca…...
Rocky系统部署k8s1.28.2单节点集群(Containerd)+Kuboard
目录 Kubernetes介绍 Kubernetes具备的功能 Kubernetes集群角色 Master管理节点组件 Node工作节点组件 非必须的集群插件 Kubernetes集群类型 Kubernetes集群规划 集群前期环境准备 开启Bridge网桥过滤 关闭SWAP交换分区 安装Containerd软件包 K8s集群部署方式 集…...
Springboot整合Flowable入门-学习笔记
目录 1、定义流程(画图) 2、Springboot部署流程 3、Springboot删除所有流程 4、Springboot根据 流程部署ID 查询 流程定义ID 5、Springboot启动(发起)流程 6、Springboot查询任务 6.1全部任务 6.2我的任务(代办任务) 7、…...
C语言常见的题目
1、 从源码到可执行文件会经历怎样的过程? 预编译:去掉空格、注释,处理预定义的指令,生成处理后的源代码文件。 编译:翻译成汇编代码,生成汇编文件。 汇编:翻译成机器码,生成一个或…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
