C++:特殊类的设计 | 单例模式

news2024/9/23 9:29:39

目录

1、特殊类的设计

2、设计一个类,不能被拷贝

3、设计一个类,只能在堆上创建对象

4、设计一个类,只能在栈上创建对象

5、设计一个类,不能被继承

6、单例模式

1、饿汉模式

2、懒汉模式


1、特殊类的设计

        在实际应用场景中,会存在一些特殊类的设计,比如:

设计一个只能在堆上创建对象的类,这样的设计可以用于需要动态管理内存,或者需要确保对象生命周期与程序控制流无关的场景中。

设计一个不能被拷贝的类,这样的设计常用于需要禁止对象被复制的场景,例如单例模式、线程池等。

 在实际场景中,还有其他的特殊类设计,下面我们来列举几个。

2、设计一个类,不能被拷贝

如果让一个类不拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可

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

class CopyBan
{
public:
	CopyBan()
	{

	}

private:
	CopyBan(const CopyBan&);
	CopyBan& operator=(const CopyBan&);
	//...
};

int main()
{
	CopyBan c;
	//CopyBan s(c);
	//CopyBan s=c;
	return 0;
}

   

而在C++11中,拓展了delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。

class CopyBan
{
public:
	CopyBan()
	{
	
	}

	CopyBan(const CopyBan&) = delete;
	CopyBan& operator=(const CopyBan&) = delete;
	//...
};
int main()
{
	CopyBan c;
	//CopyBan s(c);
	//CopyBan s=c;
	return 0;
}

3、设计一个类,只能在堆上创建对象

只能在对上创建对象,那么只能使用new来创建

1、私有化析构函数

这样在栈上创建对象会报错

2、可以使用私有的构造函数和析构函数,并通过静态成员函数返回堆上分配的对象指针。这样可以确保对象只能通过堆上的分配方式创建,而不能在栈上创建。


class HeapOnly {
private:
    // 私有构造函数和析构函数,防止在栈上创建对象
    HeapOnly() {}
    ~HeapOnly() {}

public:
    // 静态成员函数用于返回堆上分配的对象指针
    static HeapOnly* createObject() {
        return new HeapOnly();
    }
};

int main()
{
    HeapOnly* h = HeapOnly::createObject();
	//HeapOnly s;  
	return 0;
}

为防止通过拷贝构造在栈上创建对象,需要禁用拷贝构造和赋值重载。

 // 声明拷贝构造函数和赋值运算符重载为私有,不实现它们
    HeapOnly(const HeapOnly&);
    HeapOnly& operator=(const HeapOnly&);

也可以使用C++11中的delete关键字。

4、设计一个类,只能在栈上创建对象

1、同上将构造函数私有化,然后设计静态方法创建对象返回即可
class StackOnly
{
public:
 static StackOnly CreateObj()
 {
 return StackOnly();
 }
    
    // 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉
 // StackOnly obj = StackOnly::CreateObj();
 // StackOnly* ptr3 = new StackOnly(obj);
 void* operator new(size_t size) = delete;
 void operator delete(void* p) = delete;
private:
 StackOnly()  
 :_a(0)
 {}
private:
 int _a;
};

5、设计一个类,不能被继承

1、在C++98中可以将构造函数私有化派生类中调不到基类的构造函数。则无法继承

// C++98中构造函数私有化,派生类中调不到基类的构造函数。则无法继承
class NonInherit
{
public:
 static NonInherit GetInstance()
 {
 return NonInherit();
 }
private:
 NonInherit()
 {}
};

2、在C++11中使用final 关键字

 final关键字,final修饰类,表示该类不能被继承。

class A  final
{
    // ....
};

6、单例模式

单例模式是一种设计模式,用于确保类只有一个实例,并提供一个全局访问点。这在需要全局访问点且只需一个实例的情况下非常有用。

在单例模式中,类通常会提供一个静态成员函数来获取类的唯一实例,并且将构造函数设置为私有,以防止直接实例化类的对象。如果类的实例尚未创建,则静态成员函数会创建一个实例并返回它,否则会返回已存在的实例。

一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个 访问它的全局访问点,该实例被所有程序模块共享

1、饿汉模式

不管你将来用不用,程序启动时就创建一个唯一的实例对象。
// 饿汉模式
// 优点:简单
// 缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。
class Singleton
{
public:
	static Singleton* GetInstance()
	{
		return &m_instance;
	}
private:
	// 构造函数私有
	Singleton() {};

	// C++98 防拷贝
	Singleton(Singleton const&);
	Singleton& operator=(Singleton const&);

	// or

	// C++11
	Singleton(Singleton const&) = delete;
	Singleton& operator=(Singleton const&) = delete;

	static Singleton m_instance;
};
Singleton  Singleton::m_instance;
如果这个单例对象在多线程高并发环境下频繁使用,性能要求较高,那么显然使用饿汉模式来避
免资源竞争,提高响应速度更好。
饿汉模式是单例模式的一种变体,它在类加载时就创建了实例,而不是在需要时才创建。这种方式的优点是简单直接,线程安全,但可能会带来性能开销,因为实例在程序启动时就会被创建。

2、懒汉模式

懒汉模式是单例模式的另一种变体,它在需要时才创建实例,而不是在类加载时就创建。这种方式的优点是节省了内存,因为实例只在需要时才被创建,但需要考虑线程安全性。

#include <mutex>

class Singleton {
private:
    // 静态成员变量,用于保存唯一实例
    static Singleton* instance;

    // 私有构造函数,防止外部实例化对象
    Singleton() {}

    // 互斥锁,用于保证线程安全
    static std::mutex mutex;

public:
    // 静态成员函数,返回类的唯一实例
    static Singleton* getInstance() {
        // 在多线程环境下确保只有一个线程能够创建实例
        std::lock_guard<std::mutex> lock(mutex);
        // 如果实例尚未创建,则创建一个新实例
        if (!instance) {
            instance = new Singleton();
        }
        return instance;
    }
};

// 在类外初始化静态成员变量
Singleton* Singleton::instance = nullptr;
// 初始化互斥锁
std::mutex Singleton::mutex;

在这个实现中,通过互斥锁确保了在多线程环境下的线程安全性。在调用Singleton::getInstance() 时,如果实例尚未创建,则会创建一个新实例并返回,否则会直接返回已存在的实例。

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

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

相关文章

集合定义和使用方法

一.集合的长度 集合的长度,可以添加和删除,长度也会跟着去发生改变,数组一旦创建完成他的长度就不会发生改变。 二.集合的定义方式 ArrayList<String> list new ArrayList(); 三.集合能存储的数据类型 集合能够存储引用数据类型,存储基本数据类型需要使用包装类: 四…

vs配置cplex12.10

1.创建c空项目 2.修改运行环境 为release以及x64 3.创建cpp文件 4.鼠标右键点击项目中的属性 5.点击c/c&#xff0c;点击第一项常规&#xff0c;配置附加库目录 5.添加文件索引&#xff0c;主要用于把路径导进来 6.这一步要添加的目录与你安装的cplex的目录有关系 F:\program…

vue管理系统导航中添加新的iconfont的图标

1.在官网上将需要的图标&#xff0c;加入项目中&#xff0c;下载 2.下载的压缩包中&#xff0c;可以选择这两个&#xff0c;复制到项目目录中 3.如果和之前的iconfont有重复&#xff0c;那么就重新命名 4.将这里的.ttf文件&#xff0c;也重命名为自己的 5.在main文件中导入 6.在…

九泰智库 | 医械周刊- Vol.24

⚖️ 法规动态 国家药监局&#xff1a;2款创新器械获批上市 4月28日国家药品监督管理局公告&#xff0c;批准心擎医疗&#xff08;苏州&#xff09;股份有限公司“体外心室辅助设备”和“体外心室辅助泵头及管路”创新产品注册申请。 体外心室辅助设备由磁悬浮马达、控制主机…

Python语言在地球科学中地理、气象、气候变化、水文、生态、传感器等数据可视化到常见数据分析方法的使用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;Python能够运行在Linux、Windows、Macintosh、AIX操作系统上及不同平台&#xff08;x86和arm&#xff09;&#xff0c;Python简洁的语法和对动态输入的支持&#xff0c;再加上解释性语言的本质&…

U盘提示“被写保护”无法操作处理怎么办?

今天在使用U盘复制拷贝文件时&#xff0c;U盘出现“U盘被写保护”提示&#xff0c;导致U盘明明有空闲内存却无法复制的情况。这种情况很常见&#xff0c;很多人在插入U盘到电脑后&#xff0c;会出现"U盘被写保护"的提示&#xff0c;导致无法进行删除、保存、复制等操…

力扣每日一题110:平衡二叉树

题目 简单 给定一个二叉树&#xff0c;判断它是否是 平衡二叉树 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4] 输出&#xff1a;false示例 3&#xff1a; …

ComfyUI中的图像镜像反转(3种方式)

用下面的节点就可以让图片左右镜像反转&#xff0c;如下 如果想要上下翻转呢&#xff1f;用下面的节点&#xff0c;如下 这个节点不仅可以上下翻转&#xff0c;还可以左右翻转&#xff0c;把方向设置为水平就行&#xff0c;即设置为level&#xff0c;如下 或者用下面这个节点也…

动态规划——斐波那契数列模型:91.解码方法

文章目录 题目描述算法原理1.状态表示2.状态转移方程3.初始化⽅法⼀&#xff08;直接初始化&#xff09;⽅法⼆&#xff08;添加辅助位置初始化&#xff09; 4.填表顺序5.返回值 代码实现C优化Java优化 题目描述 题目链接&#xff1a;91.解码方法 算法原理 类似于斐波那契…

Elasticsearch初步认识

Elasticsearch初步认识 ES概述基本概念正向索引和倒排索引IK分词器ik_smart最少切分ik_max_word为最细粒度划分 ES索引库基本操作对索引库操作对文档操作 ES概述 Elasticsearch&#xff0c;简称为 ES&#xff0c;是一款非常强大的开源的高扩展的分布式全文检索引擎&#xff0c…

Linux基础之makefile/make

目录 一、背景 二、makefile和make的讲解 2.1 使用方法 2.2 伪目标文件 2.3 文件的属性以及属性的更新 2.4 makefile的自动推导 一、背景 这里会提及为什么要使用makefile和make&#xff0c;以及他们是什么和作用。 会不会写makefile&#xff0c;从一个侧面说明了一个人是…

JS基础:输出信息的5种方式详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端基础路线”&#xff0c;可获取完整web基础…

基于LLama3、Langchain,Chroma 构建RAG

概要&#xff1a; 使用Llama3 Langchain和ChromaDB创建一个检索增强生成&#xff08;RAG&#xff09;系统。这将允许我们询问有关我们的文档&#xff08;未包含在训练数据中&#xff09;的问题&#xff0c;而无需对大型语言模型&#xff08;LLM&#xff09;进行微调。在使用RA…

【企业动态】东胜物联正式加入EnOcean联盟,携手为智慧楼宇及能源管理提供更稳定的硬件解决方案

2024年4月&#xff0c;东胜物联&#xff08;Dusun&#xff09;宣布正式加入EnOcean联盟。EnOcean联盟是一个由来自建筑行业的400多家公司组成的全球性组织。它以EnOcean无线标准&#xff08;ISO/IEC 14543-3-10/11&#xff09;为基础&#xff0c;为可持续建筑自动化建立了创新的…

短剧APP开发:百亿短剧市场规模下的收益密码

短剧进入到大众的视野中&#xff0c;成为影视新行业&#xff0c;成为了中老年人茶余饭后的休闲方式&#xff0c;也成为了年轻人的“电子榨菜”。短剧时长短、节奏快&#xff0c;观众可以在短时间内看完一部剧&#xff0c;波澜起伏的剧情能够推动短剧的剧情&#xff0c;吸引观众…

【MRI重建】基于L+S方法的加速动态成像(MATLAB)

关于 L+S 模型很自然地可以表示动态 MRI 数据。重建欠采样数据需要 k−t 空间(采集)与 L 的奇异向量和 S 的稀疏域之间的不相干性。 L 和 S 之间的不相干性是背景和动态分量稳健分离所必需的。多线圈 L+S 重建是使用凸优化方法制定的,其中核范数用于强制 L 中的低秩,而 l1 …

58行代码把Llama 3扩展到100万上下文,任何微调版都适用 | 最新快讯

量子位公众号 QbitAI 堂堂开源之王 Llama 3&#xff0c;原版上下文窗口居然只有……8k&#xff0c;让到嘴边的一句“真香”又咽回去了。 在 32k 起步&#xff0c;100k 寻常的今天&#xff0c;这是故意要给开源社区留做贡献的空间吗&#xff1f; 开源社区当然不会放过这个机会&a…

[JUCE库]关于JUCE如何生成动态链接库 juce-7.0.1-windows

前言 当我们在使用JUCE库的时候&#xff0c;可能会需要使用到静态链接的方式&#xff0c;还好的一点是JUCE本身提供了CMake编译&#xff0c;也提供了单独的sln编译。 本文章仅针对juce-7.0.1-windows&#xff0c;由于不同版本之间差异较大&#xff0c;可能不能通用&#xff0…

Codeforces Round 943 (Div. 3) A~E

A. Maximize? Problem - A - Codeforces 给定x求出使这个式子最大的y&#xff1a; 不用想复杂直接循环枚举即可。 #include<bits/stdc.h> using lllong long; ll n,m; void solve() {int x;std::cin>>x;ll ans0,y;for(int i1;i<x;i){if(std::__gcd(i,x)i>a…

鸿蒙内核源码分析(信号量篇) | 谁在负责解决任务的同步

基本概念 信号量&#xff08;Semaphore&#xff09; 是一种实现任务间通信的机制&#xff0c;可以实现任务间同步或共享资源的互斥访问。 一个信号量的数据结构中&#xff0c;通常有一个计数值&#xff0c;用于对有效资源数的计数&#xff0c;表示剩下的可被使用的共享资源数…