c++ - 特殊类设计

文章目录

    • 一、设计一个不允许拷贝的类
    • 二、设计一个只能在堆上实例对象的类
    • 三、设计一个只能在栈上创建对象的类
    • 四、设计一个不能被继承的类
    • 五、设计一个只能创建一个对象的类(单例模式)


一、设计一个不允许拷贝的类

1、方法一:将拷贝构造和赋值重载声明不定义并且放到私有域。
解释:

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

2、方法二:直接将拷贝构造和赋值重载删除。

3、演示

//防拷贝 - 不允许拷贝
class Base1
{
public:Base1(int a = 10):_a(a){}private://c++98做法 -- 将函数声明不定义加不声明//Base1(const Base& b);//Base1& operator=(const Base& b);//c++11及以后做法 -- 将函数删除Base1(const Base1& b) = delete;Base1& operator=(const Base1& b) = delete;int _a = 0;
};void test01()
{Base1 b1;//会报错//Base1 b2(b1);
}

在这里插入图片描述

二、设计一个只能在堆上实例对象的类

1、方法:将构造函数私有化并且将拷贝构造和赋值重载删除(或者声明不定义到私有域中),再在类内部提供一个静态成员函数。
解释:

(1)将构造函数私有化:这样就只允许在类内实例类对象了。
(2)拷贝构造和赋值重载删除:在其他位置拷贝。
(3)静态成员函数:用于在堆上申请对象,并返回。

2、演示

class Base2
{
public://通过函数接口在堆上new一个对象出来static Base2& NewBase2(){Base2* b = new Base2;return *b;}private://将构造私有化Base2(int a = 10) :_a(a){};//反拷贝//c++98做法 -- 将函数声明不定义加不声明//Base2(const Base& b);//Base2& operator=(const Base& b);//c++11及以后做法 -- 将函数删除Base2(const Base2& b) = delete;Base2& operator=(const Base2& b) = delete;int _a = 0;
};void test02()
{//在栈上不行//Base2 b;//通过函数接口Base2 &b = Base2::NewBase2();//不能拷贝//Base2 b1(b);
}

三、设计一个只能在栈上创建对象的类

1、方法:将构造函数私有化并且将拷贝构造和赋值重载删除(或者声明不定义到私有域中),需要实现一个移动构造,再在类内部提供一个静态成员函数。
解释:

(1)将构造函数私有化:这样就只允许在类内实例类对象了。
(2)拷贝构造和赋值重载删除:在其他位置拷贝。
(3)静态成员函数:用于在栈上申请对象,并返回。
(4)实现移动构造:用于上述静态函数返回时使用。

2、演示

//只允许在栈上
class Base3
{
public:static Base3 StackBase3(){return Base3();}Base3(Base3&& b):_a(b._a){}
private://将构造私有化Base3(int a = 10) :_a(a){};//反拷贝//c++98做法 -- 将函数声明不定义//Base3(const Base& b);//Base3& operator=(const Base& b);//c++11及以后做法 -- 将函数删除Base3(const Base3& b) = delete;Base3& operator=(const Base3& b) = delete;int _a = 0;
};void test03()
{//不能new了//Base3* b = new Base3;//使用移动构造Base3 b = Base3::StackBase3();//防不了这种情况
//	Base3* b1 = new Base3(move(b));
}

四、设计一个不能被继承的类

1、方法一:将基类构造函数私有,这样派生类就调用不了基类的构造函数,这样就无法继承了。

class Base
{private:Base() {}
};class Derived:public Base
{
public:Derived() :Base(){}}

在这里插入图片描述

2、方法二:final关键字,final修饰类,表示该类不能被继承

class Base final
{private:Base() {}
};class Derived:public Base
{
public:
};

在这里插入图片描述

五、设计一个只能创建一个对象的类(单例模式)

1、单例模式

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

2、方法一:饿汉模式
(1)概念:就是说不管你将来用不用,程序启动时就创建一个唯一的实例对象。
(2)实现细节:

(1)在类内声明一个该类类型的静态成员变量,再到类外定义该静态成员变量。
(2)提供一个静态成员函数,返回该静态成员变量的引用。
(3)做防拷贝操作,并将该类构造函数私有化。

(3)优缺点

优点
(1)实现简单:饿汉模式在类加载时就完成了单例的初始化,这种方式简单直接,易于理解和实现。
(2)线程安全:由于单例对象在类加载时就已经创建,所以多线程环境下不会存在访问冲突,无需担心线程安全问题。
(3)执行效率高:在单例对象创建之后,所有对该单例的访问都直接返回已创建的对象,无需再进行创建或同步操作,因此在频繁访问的情况下具有较高的执行效率。
缺点
(1)资源浪费:无论是否需要使用单例对象,它都会在类加载时被创建,这可能导致在不需要使用单例对象时,系统资源被不必要地占用。特别是当单例对象占用资源较多或初始化时间较长时,这种资源浪费可能更为明显。
(2)灵活性不足:饿汉模式在类加载时就完成了单例的初始化,这意味着如果单例对象的创建依赖于某些外部条件或参数,那么这些条件或参数必须在类加载之前就已经确定或准备好,这限制了单例模式的灵活性。
(3)无法懒加载:与懒汉模式相比,饿汉模式无法实现单例对象的懒加载,即只有在真正需要时才创建单例对象。这可能会导致在某些情况下,程序启动时间较长或启动时需要加载较多的资源。

(4)演示

//饿汉模式
class Base4
{
public://返回唯一的实例的静态类static Base4& RetuntB(){return b;}//输出信息void Printf(){cout << s << endl;}private:Base4(){}Base4(const Base4& b) = delete;Base4& operator=(const Base4& b) = delete;private:string s = "hello";	//假设这是储存的信息static Base4 b;};Base4 Base4::b;void test04()
{Base4::RetuntB().Printf();}

3、方法二:懒汉模式
(1)概念:在使用时再去实例化对象。
(2)实现细节:

(1)在类内声明一个该类类型的指针,再到类外定义为nullprt
(2)提供一个静态成员函数,返回该静态成员变量的引用(再使用时发现为空就向堆申请)。
(3)做防拷贝操作,并将该类构造函数私有化。
(4)通过实现一个静态的函数来清理这块空间,或者实现一个内部类,在内部类的析构函数进行清理。

(3)优缺点

优点
(1)资源利用率高:懒汉模式实现了单例的懒加载,即单例对象在第一次被使用时才创建,这可以确保在不需要使用单例对象时不会占用系统资源,从而提高了资源利用率。
(2)灵活性高:懒汉模式的单例对象创建时机是可控的,可以根据实际需要进行调整。例如,可以在单例对象创建时传入参数或依赖于外部条件,这增加了单例模式的灵活性。
适用于多种情况:由于懒汉模式可以根据需要创建单例对象,因此它适用于那些单例对象创建成本较高或初始化时间较长的情况。、
缺点
(1)线程安全问题:在多线程环境下,懒汉模式需要确保单例对象的唯一性。如果没有适当的同步机制,可能会出现多个线程同时创建单例对象的情况,导致单例模式失效。因此,需要加锁来确保线程安全,但这会增加性能开销。
(2)性能开销:为了实现线程安全,懒汉模式通常需要在访问单例对象时加锁。虽然这可以确保单例对象的唯一性,但频繁的加锁和解锁操作会降低程序的性能。特别是在高并发场景下,这种性能开销可能更加明显。
(3)双重检查锁定(Double-Checked Locking)的复杂性:为了解决懒汉模式的线程安全问题,同时减少性能开销,可以使用双重检查锁定技术。但这种技术实现起来较为复杂,且容易出错。如果实现不当,可能会导致单例模式失效或引入新的线程安全问题。

//懒汉模式
class Base5
{
public://返回唯一的实例的静态类static Base5& RetuntP(){if (p == nullptr){p = new Base5;}return *p;}//输出信息void Printf(){cout << s << endl;}//释放方法1 --- 实例一个内部类,当内部类释放了,p也会跟着释放class DeleteP{public:~DeleteP(){if (p != nullptr)delete p;}};释放方法二 --- 通过手动调用函数释放//void DeleteP()//{//	if (p != nullptr)//		delete p;//}private:Base5(){}Base5(const Base5& b) = delete;Base5& operator=(const Base5& b) = delete;private:string s = "hello";	//假设这是储存的信息static Base5* p;};//初始化
Base5* Base5::p = nullptr;//实例一个内部类,当内部类生命周期结束后会释放 p
Base5::DeleteP del;

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

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

相关文章

多云网络部署存在挑战,F5分布式云应用简化方案解读

伴随着人工智能与云计算领域的深度融合与集中爆发&#xff0c;企业在多云环境中面临着挑战&#xff0c;包括复杂性、成本和风险的增加等……对于高度敏捷企业中的开发团队而言&#xff0c;传统网络的沉重运维成本和低效率将会成为发展的障碍。作为一家提供多云应用安全和应用交…

TcpSocket在切后台后如何保活

1&#xff09;TcpSocket在切后台后如何保活 2&#xff09;Magica Clothes 2插件与Burst编译问题 3&#xff09;粒子拖尾合批失败怎么办 4&#xff09;如何让射线追踪跟随我FPS游戏的十字准星进行移动 这是第398篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的热门话题&…

flink文档刨析

flink任务运行方式 flink任务提交方式有3种 session、per-job、application三种 flink任务运行底座也有三种&#xff0c;Standalone、yarn、k8s 原则上一个flink任务运行的方式由3*39种&#xff0c;但是有些是没法搭配的 yarn&#xff1a;包括yarn-session 、yarn-per-job 、…

uni-app 吸顶方案总结

效果 页面级 uni.pageScrollTo 官方文档&#xff1a;https://uniapp.dcloud.net.cn/api/ui/scroll.html#pagescrollto 原生头部导航 uni.pageScrollTo({selector: #tabs,duration: 300 });(推荐)需要兼容自定义头部导航 <template><view id"demo1" :styl…

Vue框架学习笔记-6

Vue中的路由 Vue中的路由&#xff08;Routing&#xff09;是通过Vue Router这个官方提供的路由管理器来实现的。Vue Router允许你通过不同的URL访问应用中不同的页面&#xff08;组件&#xff09;&#xff0c;而无需重新加载页面。这对于构建单页应用&#xff08;SPA, Single …

【Hadoop】建立圈内组件的宏观认识

01存储02计算03调度04其他05回忆 众多组件们构建了大规模分布式计算和存储平台。本文介绍Hadoop生态圈中各个组件的主要功能和作用&#xff0c;辅助学者理解每个组件的定位和用途&#xff0c;从而建立对圈内组件的宏观认识。梳理清楚HDFS、MapReduce、YARN、Hive、HBase、Spark…

推出 SAM 2:适用于视频和图像的下一代 Meta Segment Anything 模型

继图像元分割模型(SAM) 取得成功之后&#xff0c;我们发布了SAM 2&#xff0c;这是一个用于在图像和视频中实时提示对象分割的统一模型&#xff0c;可实现最先进的性能。 为了秉承我们的开放科学方针&#xff0c;我们通过宽松的 Apache 2.0 许可证共享代码和模型权重。 我们还…

传奇游戏为何采用多渠道发布如何有效利用论坛资源?

揭秘传奇游戏多渠道发布策略&#xff0c;探讨手机游戏发布论坛如何助力品牌形象塑造 游戏发布平台|手机游戏发布平台|公益服游戏发布站 问题&#xff1a;传奇游戏为何采用多渠道发布策略&#xff1f;这些渠道各自有何优劣势&#xff1f; 回答&#xff1a;传奇游戏采用多渠道发…

Github 2024-08-14 C开源项目日报Top10

根据Github Trendings的统计,今日(2024-08-14统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目10Objective-C项目1PHP项目1Python项目1PHP:流行的Web开发脚本语言 创建周期:4710 天开发语言:C, PHP协议类型:OtherStar数量:37340 …

JAVA中new Object对象占用多少字节,Java对象的组成是哪些?Java对象头的组成又是哪些,MarkWord是什么,有什么作用?

Java对象头的组成_java对象头结构-CSDN博客 JAVA中new Object对象占用多少字节&#xff0c;Java对象的组成是哪些&#xff1f;Java对象头的组成又是哪些&#xff0c;MarkWord是什么&#xff0c;有什么作用&#xff1f; 一、JAVA对象的结构组成 JAVA Object对象的结构组成&…

FreeRTOS的任务创建和删除

1、任务创建和删除的API函数 任务的创建和删除本质就是调用FreeRTOS的API函数。 和任务创建和删除有关的函数主要有三&#xff1a; xTaskCreate():动态方式创建任务。 xTaskCreateStatic():静态方式创建任务。 vTaskDelete():删除任务。 那又有思考了 2、动态方式创建任…

实验五之用Processing绘画

1.案例代码如下&#xff1a; import generativedesign.*; import processing.pdf.*; import java.util.Calendar; Tablet tablet; boolean recordPDF false; float x 0, y 0; float stepSize 5.0; PFont font; String letters "Sie hren nicht die folgenden Gesnge…

超级字符串技能:提升你的编码游戏

嘿嘿,uu们,今天咱们来详解字符函数与字符串函数,好啦,废话不多讲,开干&#xff01; 1.:字符分类函数 C语言中又一系列的函数是专门做字符分类的,也就是一个字符属于什么类型的字符的,这些函数的使用需要包含头文件ctype.h 这些函数的使用方法都十分类似,博主在这里就举两到三个…

【C语言篇】C语言常考及易错题整理DAY3

文章目录 选择题整形提升与算术转换左移右移操作符操作符优先级与结合性后置指针变量基本知识 编程题最大连续1的个数完全数计算单词倒排面试题.珠玑妙算两数之和 选择题 整形提升与算术转换 声明以下变量&#xff0c;则表达式: ch/i (f*d – i) 的结果类型为&#xff08; &…

<Qt> 系统 - 网络编程 | 音视频

目录 前言&#xff1a; 一、QUdpSocket &#xff08;一&#xff09;核心 API 概览 &#xff08;二&#xff09;设计一个UDP回显服务器 二、QTCPSocket &#xff08;一&#xff09;核心 API 概览 &#xff08;二&#xff09;设计一个TCP回显服务器 三、HTTP Client 四、…

msgqueue.hpp队列模块

目录 一.MsgQueue模块介绍 二.MsgQueue类的实现 成员变量 构造函数与析构函数 成员函数 参数设置函数 setArgs 参数获取函数 getArgs 三.MsgQueueMapper类的实现 成员变量 构造函数 成员函数 创建表格函数 createTable 删除表格函数 dropTable 插入数据函数 inse…

GPT-4o:开启多模态AI识别新纪元

GPT-4o功能简介 在人工智能的演变历程中&#xff0c;图像识别技术始终占据着核心地位。技术的发展日新月异&#xff0c;使得AI不仅能够识别图像内容&#xff0c;还能将其转化为文字描述。特别值得一提的是&#xff0c;OpenAI在春季发布的GPT-4o模型&#xff0c;将图像识别技术…

微软Detours Hook库编译与使用

Detours 是微软开发的一个强大的Windows API钩子库&#xff0c;用于监视和拦截函数调用。它广泛应用于微软产品团队和众多独立软件开发中&#xff0c;旨在无需修改原始代码的情况下实现函数拦截和修改。Detours 在调试、监控、日志记录和性能分析等方面表现出色&#xff0c;已成…

shell命令行解释器—既陌生有熟悉的东西

今天做一个感性的认识来&#xff0c;用一个生活的例子。 你生活在有一条村子里面&#xff0c;在村的东边就是王婆&#xff0c;王婆呢&#xff1f;她主要做什么呢啊&#xff1f;她在村儿里面呢&#xff0c;也不种地啊&#xff0c;那她干什么呢&#xff1f;他主要做帮别人进行婚嫁…

【TabBar嵌套Navigation案例-发现页面-按钮上的图片旋转 Objective-C语言】

一、接下来,我们来做这个,点击以后,让它出一个蓝色的View 1.就是我们示例程序的这种效果, 一点击,让这个按钮旋转,然后呢,再让它出来一个蓝色的View, 首先,我们要去监听它的点击事件,这是第一,我点击以后,我要做一些什么样的操作,要有点击事件, 所以呢,我要把…