C++——特殊类

特殊类


文章目录

  • 特殊类
  • 一、请设计一个类,不能被拷贝
  • 二、请设计一个类,只能在堆上创建对象
    • 方案一:析构函数私有化
    • 方案二:构造函数私有化
  • 三、请设计一个类,只能在栈上创建对象
  • 四、请设计一个类,不能被继承
  • 五、请设计一个类,只能创建一个对象(单例模式)
    • 饿汉模式
    • 懒汉模式


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

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

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

原因:

  1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不能禁止拷贝了
  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了,但一定要声明,不然会默认生成
class CopyBan
{// ...
private:CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);//...
};

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

class CopyBan
{// ...CopyBan(const CopyBan&) = delete;CopyBan& operator=(const CopyBan&) = delete;//...
};

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

方案一:析构函数私有化

实现方式:

  1. 将类的析构函数设为私有
  2. 提供一个公有成员函数,在该公有成员函数中完成堆对象的析构
class HeapOnly
{
public:/*static void Destroy(HeapOnly* ptr){delete ptr;}*/void Destroy(){delete this;}
private:~HeapOnly(){cout << "~HeapOnly()" << endl;}
};

方案二:构造函数私有化

实现方式:

  1. 将类的构造函数私有,拷贝构造声明成私有或delete,防止别人调用拷贝在栈上生成对象
  2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建
class HeapOnly
{
public:static HeapOnly* CreateObj(){return new HeapOnly;}private://C++98//HeapOnly(const HeapOnly& hp);//C++11HeapOnly(const HeapOnly& hp) = delete;HeapOnly(){cout << "HeapOnly()" << endl;}
};

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

实现方式:将构造函数私有化,然后设计静态方法创建对象返回

class StackOnly
{
public:static StackOnly CreateObj(){StackOnly obj;return obj;}void* operator new(size_t size) = delete;// 实现类专属的operator new// new这个类对象时,operator new就会调用这个,不会调全局的//StackOnly obj = StackOnly::CreateObj();//StackOnly* ptr = (StackOnly*)new StackOnly(obj);//void* operator new(size_t size)//{//	cout << "void* operator new(size_t size)" << endl;//	return malloc(size);//}private:StackOnly(){cout << "StackOnly()" << endl;}
};

值得注意的是,需要把operator new函数delete掉,否则如果在类外定义,还是可以动态开辟空间

class StackOnly
{
public:static StackOnly CreateObj(){StackOnly obj;return obj;}//void* operator new(size_t size) = delete;// 实现类专属的operator new// new这个类对象时,operator new就会调用这个,不会调全局的//StackOnly obj = StackOnly::CreateObj();//StackOnly* ptr = (StackOnly*)new StackOnly(obj);void* operator new(size_t size){cout << "void* operator new(size_t size)" << endl;return malloc(size);}private:StackOnly(){cout << "StackOnly()" << endl;}
};int main()
{StackOnly obj = StackOnly::CreateObj();StackOnly* ptr = (StackOnly*)new StackOnly(obj);return 0;
}

在这里插入图片描述

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

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

class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};

C++11:final关键字,final修饰类,表示该类不能被继承

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

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

设计模式:

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结
为什么会产生设计模式这样的东西呢?
就像人类历史发展会产生兵法,最开始部落之间打仗时都是人拼人的对砍,后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后来孙子就总结出了《孙子兵法》,写代码也是类似,也有套路

使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。,设计模式使代码编写真正工程化,设计模式是软件工程的基石脉络,如同大厦的结构一样

单例模式:

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

饿汉模式

饿汉模式
优点:简单
缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定

// 饿汉模式:提前(main函数启动时)创建好实例对象
// 优点:实现简单
// 缺点:1、可能会导致进程启动慢、2、如果两个单例有启动先后顺序,那么饿汉无法控制
class A
{
public:static A* GetInstance(){return &_inst;}void Add(const string& key, const string& value){_dict[key] = value;}void Print(){for (auto& kv : _dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;}
private:A(){}A(const A& aa) = delete;A& operator=(const A& aa) = delete;map<string, string> _dict;int _n = 0;static A _inst;
};

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

懒汉模式

懒汉模式
优点:第一次使用实例对象时创建对象,进程启动无负载,多个单例实例启动顺序自由控制
缺点:复杂

// 懒汉模式:第一次用的时候再创建(现吃现做)
// todo:线程安全问题
// new的懒汉对象一般不需要释放,进程正常结束会释放资源
// 如果需要做一些动作,比如持久化,那么可以利用gc类static对象搞定
class B
{
public:static B* GetInstance(){if (_inst == nullptr){_inst = new B;}return _inst;}void Add(const string& key, const string& value){_dict[key] = value;}void Print(){for (auto& kv : _dict){cout << kv.first << ":" << kv.second << endl;}cout << endl;}static void DelInstance(){if (_inst){delete _inst;_inst = nullptr;}}private:B(){}~B(){// 持久化:要求把数据写到文件cout << "数据写到文件" << endl;}B(const B& aa) = delete;B& operator=(const B& aa) = delete;map<string, string> _dict;int _n = 0;static B* _inst;class gc{public:~gc(){DelInstance();}};static gc _gc;
};B* B::_inst = nullptr;
B::gc B::_gc;

此处需要注意的是由于懒汉模式的单例对象是new出来的,大部分情况下这个单例对象是不需要回收的,由于进程使用的是虚拟地址,由页表映射到物理地址,所以等进程结束时,会发生解页表操作,此时动态分配的空间在系统的层面上被回收了

但如果我们还是希望能够自主控制这个单例何时释放空间或者当main函数结束的时候单例能够自动回收空间的话,可以实现一个内部类,进行回收操作

理由:我们不能把new出来的单例对象放在单例的析构函数中delete,因为如果这样会发生无限递归函数的情况,导致栈溢出,所以我们需要额外写一个函数接口能够自主将new出的单例对象空间释放,同时我们希望main函数结束的时候,如果该空间未释放,能够做到自动回收这份new出来的空间,此时内部类的回收机制就完全符合了我们的要求,也就是说内部类是解决问题的最优解

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


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

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

相关文章

微软Office Plus与WPS Office的较量:办公软件市场将迎来巨变?

微软Office Plus在功能表现上远超WPS Office&#xff1f; 微软出品的Office套件实力强劲&#xff0c;其不仅在办公场景中扮演着不可或缺的角色&#xff0c;为用户带来高效便捷的体验&#xff0c;而且在娱乐生活管理等多元领域中同样展现出了卓越的应用价值 作为中国本土办公软…

Leetcode 第 381 场周赛题解

Leetcode 第 381 场周赛题解 Leetcode 第 381 场周赛题解题目1&#xff1a;3014. 输入单词需要的最少按键次数 I思路代码复杂度分析 题目2&#xff1a;3015. 按距离统计房屋对数目 I思路代码复杂度分析 题目3&#xff1a;3016. 输入单词需要的最少按键次数 II思路代码复杂度分析…

HarmonyOS使用Web组件加载页面

1、加载网络页面 在Web组件创建时&#xff0c;指定默认加载的网络页面 。在默认页面加载完成后&#xff0c;如果开发者需要变更此Web组件显示的网络页面&#xff0c;可以通过调用loadUrl()接口加载指定的网页。 默认在Web组件加载完“www.baidu.com”页面后&#xff0c;点击按…

html+js+css静态故宫主题

登录代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>登录 - 故宫博物院</title><…

C语言菜鸟入门·函数

目录 1. 函数的定义 2. 函数声明 3. 函数调用 4. 函数参数 4.1 传值调用 4.2 引用调用 函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数&#xff0c;即主函数 main() &#xff0c;所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同…

【C++】C++入门—— 引用

引用 1 前情提要2 概念剖析3 引用特性4 常引用5 使用场景5.1做参数5.2 做返回值 6 传值 传引用的效率比较7 引用与指针的差异Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读下一篇文章见 1 前情提要 在C语言中&#xff0c;我们往往会遇见复杂的指针&#xff08;如…

论文阅读-MapReduce

论文名称&#xff1a;MapReduce: Simplified Data Processing on Large Clusters 翻译的效果不是很好&#xff0c;有空再看一遍&#xff0c;参照一下别人翻译的。 MapReduce:Simplified Data Processing on Large Clusters 中文翻译版(转) - 阿洒 - 博客园 (cnblogs.com) 概…

C#,欧拉数(Eulerian Number)的算法与源代码

1 欧拉数 欧拉数特指 Eulerian Number&#xff0c;不同于 Euler numbers&#xff0c;Eulers number 哦。 组合数学中&#xff0c;欧拉数&#xff08;Eulerian Number&#xff09;是从1到n中正好满足m个元素大于前一个元素&#xff08;具有m个“上升”的排列&#xff09;条件的…

mini-spring 实现应用上下文,自动识别、资源加载、扩展机制

我们不能让面向 Spring 本身开发的 DefaultListableBeanFactory 服务&#xff0c;直接给予用户使用 DefaultListableBeanFactory、XmlBeanDefinitionReader&#xff0c;是我们在目前 Spring 框架中对于服务功能测试的使用方式&#xff0c;它能很好的体现出 Spring 是如何对 xm…

【靶场实战】Pikachu靶场暴力破解关卡详解

Nx01 系统介绍 Pikachu是一个带有漏洞的Web应用系统&#xff0c;在这里包含了常见的web安全漏洞。 如果你是一个Web渗透测试学习人员且正发愁没有合适的靶场进行练习&#xff0c;那么Pikachu可能正合你意。 Nx02 Burte Force概述 “暴力破解”是一攻击具手段&#xff0c;在web…

Transformer 自然语言处理(二)

原文&#xff1a;Natural Language Processing with Transformers 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第五章&#xff1a;文本生成 基于 Transformer 的语言模型最令人不安的特点之一是它们生成的文本几乎无法与人类写的文本区分开。一个著名的例子是 Ope…

60、Flink CDC 入门介绍及Streaming ELT示例(同步Mysql数据库数据到Elasticsearch)-完整版

Flink 系列文章 一、Flink 专栏 Flink 专栏系统介绍某一知识点&#xff0c;并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分&#xff0c;比如术语、架构、编程模型、编程指南、基本的…

【Docker】在Windows下使用Docker Desktop创建nginx容器并访问默认网站

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是《Docker容器》序列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对…

布局技巧及CSS初始化

一&#xff0c;margin负值巧妙应用 二&#xff0c;文字围绕浮动元素 三&#xff0c;行内块 四&#xff0c;CSS三角强化 五&#xff0c;CSS初始化 一&#xff0c;margin负值巧妙应用 制作盒子的细线边框&#xff1a; 鼠标经过li后变色&#xff1a; 二&#xff0c;文字围绕…

Redis缓存穿透、缓存击穿、缓存雪崩的解决方案

一、背景 不管是实际工作还是面试&#xff0c;这3个问题都是非常常见的&#xff0c;今天我们就好好探讨一下这个三个问题的解决方案 三者的区别&#xff1a; 缓存穿透&#xff1a;查询缓存和数据库都不存在的数据&#xff0c;缓存没有&#xff0c;数据库也没有 缓存击穿&#…

Java入门高频考查基础知识8(腾讯18问1.5万字参考答案)

刷题专栏&#xff1a;http://t.csdnimg.cn/gvB6r Java 是一种广泛使用的面向对象编程语言&#xff0c;在软件开发领域有着重要的地位。Java 提供了丰富的库和强大的特性&#xff0c;适用于多种应用场景&#xff0c;包括企业应用、移动应用、嵌入式系统等。 以下是几个面试技巧&…

使用AKStream对接gb28181

优点&#xff1a;功能比较多&#xff0c;C#开发的&#xff0c;容易修改&#xff0c;内嵌入了zlmk流媒体服务品&#xff0c;启动简单 缺点&#xff1a;sip对摄像头兼容还有问题&#xff0c;大华接入非常不稳定&#xff0c;注册等待时间久&#xff0c;对海康是正常&#xff0c;占…

IntelliJ Idea实用插件推荐

目录 一、插件安装 二、常用插件 A、代码规范 Alibaba Java Coding Guidelines SonarLint B、快捷开发 aiXcoder-AI代码生成 AWS Toolkit-AI代码生成 CodeGeeX-AI代码生成 CodeGlance-代码缩略图 camelCase-格式转换 GsonFormatPlus-json代码生成 Sequence Giagram…

UE4 CustomDepthMobile流程小记

原生UE opaque材质中获取CustomDepth/CustomStencil会报错 在其Compile中调用的函数中没有看到报错逻辑 材质节点的逻辑都没有什么问题&#xff0c;所以看一下报错 在HLSLMaterialTranslator::Translate中 修改之后 mobile流程的不透明材质可以直接获取SceneTexture::customd…

聚焦AI新动能,九州未来与燧弘华创签约!

1月24日&#xff0c;厦门市电子信息与人工智能产业高质量发展大会成功举办。来自电子信息产业、人工智能领域的企业家、专家等近300位嘉宾齐聚一堂&#xff0c;共谋智能基础&#xff0c;共话产业合作&#xff0c;共享发展商机。 会上&#xff0c;九州未来与燧弘华创签署算力租…