C++----特殊类的设计

文章目录

  • 特殊类的设计
    • 设计一个类不能被拷贝
    • 设计一个类,只能在堆上创建对象
    • 设计一个类,只能在栈上创建对象
    • 设计一个类,不能被继承
    • 设计一个类,只能创建一个对象(单例模式)
      • 设计模式
      • 单例模式
        • 概念
        • 单例模式的实现

特殊类的设计

设计一个类不能被拷贝

IO流也是不允许拷贝的

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

  • 实现:分为C++11之前和C++11以及C++11之后

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

      class CopyBan
      {// ...
      private:CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);//...
      };
      
      • 设计为私有的原因:如果不设计为私有,那么用户可以在类外对这个构造函数和析构函数进行定义,这样的话就又能拷贝了。为了防止这种情况才设计为私有。 赋值重载设置为私有的原因也是如此
        设计为公有导致在类外定义构造函数,使得又能被拷贝的场景

        class ListNode
        {
        public:ListNode(const ListNode& node);ListNode() = default;
        private:string _s;
        };ListNode::ListNode(const ListNode& node)
        {_s = node._s;cout << _s << endl;
        }int main()
        {ListNode node;ListNode copenode(node);
        }
        
      • 只声明不定义的原因:不定义是因为该函数根本不会调用,定义了其实也没有什么意义

    • C++11

      • C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上 =delete,表示让编译器删除掉该默认成员函数。*
        delete后,就删除掉了该默认成员函数,在public中删除,还是在private中删除都是可以的。类外无法去定义该函数,因为该函数被删除了

      • 样例

        class ListNode
        {
        public:ListNode(const ListNode& node) = delete;ListNode() = default;
        private:string _s;
        };//ListNode::ListNode(const ListNode& node)
        //{
        //	_s = node._s;
        //	cout << _s << endl;
        //}int main()
        {ListNode node;//ListNode copenode(node);
        }
        

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

  • 思路1
    **将类的构造函数私有,拷贝构造声明成私有/删除拷贝构造。**防止别人调用拷贝在栈上生成对象。 然后提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建

    • 样例

      class HeapOnly
      {
      public:static HeapOnly* CreateObject(){return new HeapOnly;}
      private:HeapOnly() {}// C++98// 1.只声明,不实现。因为实现可能会很麻烦,而你本身不需要// 2.声明成私有HeapOnly(const HeapOnly&);// or// C++11    HeapOnly(const HeapOnly&) = delete;
      };int main()
      {	HeapOnly* p1 = HeapOnly::GreatObj();//HeapOnly p2(*p1); 上面防拷贝是为了应对这种情况。
      }
      

      1

  • 思路2:析构函数私有化,然后提供一个 销毁new出来对象的函数Destroy

    class HeapOnly
    {
    public:void Destroy(){delete this;}
    private:~HeapOnly(){}
    };int main()
    {	HeapOnly* p1 = HeapOnly::GreatObj();//HeapOnly p2(*p1); 上面不用封拷贝构造的原因是 析构函数被封了,p2创建不出来
    }
    

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

  • **关于operator new 与 operator delete:**当一个类重载了 关键字new后,那么new 这个对象的时候,是调用这个operator new 来创建对象。

  • 思路1
    将构造函数私有化,然后设计静态方法创建对象返回即可。并且把 operator new 给delete。

    • 样例

      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;
      };int main()
      {// StackOnly* p1 = new StackOnly; 是调不动的StackOnly p2 = StackOnly::CreateObj();StackOnly p3(p2);
      }
      
    • 缺陷:该方法无法给封住静态成员,而静态成员在静态区。

  • 思路2
    把构造函数,拷贝构造封死。提供移动构造

    • 样例

      class StackOnly
      {
      public:static StackOnly CreateObj(){return StackOnly();}StackOnly(StackOnly&& sty){}StackOnly(const StackOnly& cop) = delete;
      private:StackOnly():_a(0){}
      private:int _a;
      };int main()
      {// StackOnly* p1 = new StackOnly; 是调不动的//StackOnly p3(p2);StackOnly p2 = StackOnly::CreateObj();//缺陷static StackOnly p3(move(p2));StackOnly p4 = new StackOnly(move(p2));
      }
      
    • 缺陷:当原对象被move后,可以把对象创建到堆上,也可以创建到栈上

设计一个类,不能被继承

单例模式的实现

单例模式的实现有两种方式:饿汉模式,懒汉模式

  • 饿汉模式

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

    • 概念:无论将来用不用,程序启动时就创建一个唯一的实例对象。

    • 思路
      将析构函数设为私有,此举防止了直接构造出对象
      在类域中声明 该类的静态对象。注意:这也是此后该类实例化的唯一一个成员
      防拷贝。这是为了防止 通过该类的静态对象拷贝构造出新的对象
      注意:静态变量是在进入main函数前就被创建的

    • 代码实现样例

      class Singleton
      {
      public:static Singleton* GetInstance(){return &m_instance;}
      private:// 构造函数私有Singleton() {};// C++98 防拷贝Singleton(Singleton const&);Singleton& operator=(Singleton const&);// or// C++11Singleton(Singleton const&) = delete;Singleton& operator=(Singleton const&) = delete;//这里的m_instance不是Singleton的成员,而是声明静态变量m_instance,并将其限制到类域中static Singleton m_instance;
      };
      Singleton Singleton::m_instance;
    • 缺点

      1. 多个饿汉模式的单例,某个对象初始化内容较多(读文件),会导致程序慢
      2. 如果A和B两个饿汉对象初始化存在依赖关系,要求A先初始化,B再初始化,饿汉无法保证
  • 懒汉模式

    懒汉模式是在第一次使用实例对象的时候创建对象

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

    • 思路:在饿汉模式的基础上,将声明的静态对象改为静态对象指针,静态对象指针定义为nullptr,并且在调用时当静态对象指针为nullptr时对其实例化,后续不再实例化

    • 代码实现样例

      //懒汉模式
      class InfoMgr
      {
      public://C++11前static InfoMgr& GetInstance(){// 第一次调用时创建单例对象// 线程安全的风险if (_pins == nullptr){_pins = new InfoMgr;}return *_pins;}void Print(){cout << _ip << endl;cout << _port << endl;cout << _buffSize << endl;}static void DelInstance(){delete _pins;_pins = nullptr;}private:InfoMgr(const InfoMgr&) = delete;InfoMgr& operator=(const InfoMgr&) = delete;InfoMgr(){cout << "InfoMgr()" << endl;}
      private:string _ip = "127.0.0.1";int _port = 80;size_t _buffSize = 1024 * 1024;//...static InfoMgr* _pins;
      };InfoMgr* InfoMgr::_pins = nullptr;
      
    • 缺点:有线程安全的风险

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

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

相关文章

鸿蒙实战:使用隐式Want启动Ability

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙应用项目2.2 修改Index.ets代码2.3 创建LuzhouAbility2.4 创建Luzhou页面2.5 设置模块配置文件 3. 测试效果4. 实战总结 1. 实战概述 本次鸿蒙应用实战&#xff0c;先创建项目“ImplicitWantStartAbility”&#xff0c;接着修改In…

NLP论文速读(多伦多大学)|利用人类偏好校准来调整机器翻译的元指标

论文速读|MetaMetrics-MT: Tuning Meta-Metrics for Machine Translation via Human Preference Calibration 论文信息&#xff1a; 简介&#xff1a; 本文的背景是机器翻译&#xff08;MT&#xff09;任务的评估。在机器翻译领域&#xff0c;由于不同场景和语言对的需求差异&a…

AJAX学习(24.11.1-24.11.14)(包含HTTP协议)

AJAX学习&#xff08;24.11.1-11.14) 来源&#xff1a; 传智 | 高校学习平台-首页 传智播课&#xff1a;黑马程序员 1.服务器和客户端 1.服务器&#xff1a;存放和对外提供资源的电脑。 2.客户端&#xff08;用户&#xff09;&#xff1a;获取和消费资源的电脑。&#xff0…

好用的js组件库

lodash https://www.lodashjs.com/https://www.lodashjs.com/ uuid 用于生成随机数&#xff0c;常用于生成id标识 GitHub - uuidjs/uuid: Generate RFC-compliant UUIDs in JavaScripthttps://github.com/uuidjs/uuid dayjs 常用于时间的处理 安装 | Day.js中文网 (fenxi…

基于麒麟服务器操作系统V10版本,部署Nginx服务、MySql服务搭建PHP环境,实现静态网站平台的搭建。

一、环境准备 关闭防火墙。 查看当前防火墙的状态 systemctl status firewalld Copy 如果防火墙的状态参数是inactive,则防火墙为关闭状态。 如果防火墙的状态参数是active,则防火墙为开启状态。 关闭防火墙。 如果您想临时关闭防火墙,需要运行以下命令: systemctl…

[JavaWeb] 尚硅谷JavaWeb课程笔记

1 Tomcat服务器 Tomcat目录结构 bin&#xff1a;该目录下存放的是二进制可执行文件&#xff0c;如果是安装版&#xff0c;那么这个目录下会有两个exe文件&#xff1a;tomcat10.exe、tomcat10w.exe&#xff0c;前者是在控制台下启动Tomcat&#xff0c;后者是弹出GUI窗口启动To…

SRP 实现 Cook-Torrance BRDF

写的很乱&#xff01; BRDF&#xff08;Bidirectional Reflectance Distribution Function&#xff09;全称双向反射分布函数。辐射量单位非常多&#xff0c;这里为方便直观理解&#xff0c;会用非常不严谨的光照强度来解释说明。 BRDF光照模型&#xff0c;上反射率公式&#…

向量数据库FAISS之五:原理(LSH、PQ、HNSW、IVF)

1.Locality Sensitive Hashing (LSH) 使用 Shingling MinHashing 进行查找 左侧是字典&#xff0c;右侧是 LSH。目的是把足够相似的索引放在同一个桶内。 LSH 有很多的版本&#xff0c;很灵活&#xff0c;这里先介绍第一个版本&#xff0c;也是原始版本 Shingling one-hot …

基于YOLOv8深度学习的无人机航拍小目标检测系统(PyQt5界面+数据集+训练代码)

本研究提出并实现了一种基于YOLOv8深度学习模型的无人机航拍小目标检测系统&#xff0c;旨在解决高空环境下汽车目标检测的技术难题。随着无人机技术的发展&#xff0c;航拍图像已广泛应用于交通监控、城市管理、灾害应急等多个领域。然而&#xff0c;由于无人机通常在较高的飞…

LeetCode 热题 100 回顾

目录 一、哈希部分 1.两数之和 &#xff08;简单&#xff09; 2.字母异位词分组 &#xff08;中等&#xff09; 3.最长连续序列 &#xff08;中等&#xff09; 二、双指针部分 4.移动零 &#xff08;简单&#xff09; 5.盛最多水的容器 &#xff08;中等&#xff09; 6…

使用 PyTorch 实现 ZFNet 进行 MNIST 图像分类

在本篇博客中&#xff0c;我们将通过两个主要部分来演示如何使用 PyTorch 实现 ZFNet&#xff0c;并在 MNIST 数据集上进行训练和测试。ZFNet&#xff08;ZFNet&#xff09;是基于卷积神经网络&#xff08;CNN&#xff09;的图像分类模型&#xff0c;广泛用于图像识别任务。 环…

【计算机网络实验】之静态路由配置

【计算机网络实验】之静态路由配置 实验题目实验目的实验任务实验设备实验环境实验步骤路由器配置设置静态路由测试路由器之间的连通性配置主机PC的IP测试 实验题目 静态路由协议的配置 实验目的 熟悉路由器工作原理和机制&#xff1b;巩固静态路由理论&#xff1b;设计简单…

driver.js实现页面操作指引

概述 在访问某些网站的时候&#xff0c;第一次进去你会发现有个操作指引&#xff0c;本文引用driver.js&#xff0c;教你在你的页面也加入这般高大上的操作指引。 实现效果 实现 driver.js简介 driver.js是一个功能强大且高度可定制的基于原生JavaScript开发的新用户引导库…

无人机航测技术算法概述!

一、核心技术 传感器技术&#xff1a; GPS/GLONASS&#xff1a;无人机通过卫星定位系统实现高精度的飞行控制和数据采集。 高清相机&#xff1a;用于拍摄地面图像&#xff0c;通过后续图像处理生成三维模型。 激光雷达&#xff08;LiDAR&#xff09;&#xff1a;通过激光扫…

Docker 基础命令介绍和常见报错解决

介绍一些 docker 可能用到的基础命令&#xff0c;并解决三个常见报错&#xff1a; 权限被拒绝&#xff08;Permission Denied&#xff09;无法连接到 Docker 仓库&#xff08;Timeout Exceeded&#xff09;磁盘空间不足&#xff08;No Space Left on Device&#xff09; 命令以…

Java RPC框架的接口预热原理及无损实现

&#x1f680; 博主介绍&#xff1a;大家好&#xff0c;我是无休居士&#xff01;一枚任职于一线Top3互联网大厂的Java开发工程师&#xff01; &#x1f680; &#x1f31f; 在这里&#xff0c;你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人&#xff0c;我不仅热衷…

java的强,软,弱,虚引用介绍以及应用

写在前面 本文看下Java的强&#xff0c;软&#xff0c;弱&#xff0c;虚引用相关内容。 1&#xff1a;各种引用介绍 顶层类是java.lang.ref.Reference,注意是一个抽象类&#xff0c;而不是接口&#xff0c;其中比较重要的引用队列ReferenceQueue就在该类中定义&#xff0c;子…

已有docker增加端口号,不用重新创建Docker

已有docker增加端口号&#xff0c;不用重新创建Docker 1. 整体描述2. 具体实现2.1 查看容器id2.2 停止docker服务2.3 修改docker配置文件2.4 重启docker服务 3. 总结 1. 整体描述 docker目前使用的非常多&#xff0c;但是每次更新都需要重新创建docker&#xff0c;也不太方便&…

jmeter常用配置元件介绍总结之断言

系列文章目录 1.windows、linux安装jmeter及设置中文显示 2.jmeter常用配置元件介绍总结之安装插件 3.jmeter常用配置元件介绍总结之线程组 4.jmeter常用配置元件介绍总结之函数助手 5.jmeter常用配置元件介绍总结之取样器 6.jmeter常用配置元件介绍总结之jsr223执行pytho…

OpenLayers教程12_WebGL自定义着色器:实现高级渲染效果

在 OpenLayers 中使用 WebGL 自定义着色器实现高级渲染效果 目录 一、引言二、WebGL 自定义着色器的优势三、示例应用&#xff1a;实现动态渲染效果 1. 项目结构2. 主要代码实现3. 运行与效果 四、代码讲解与扩展 1. 动态圆的半径和填充颜色2. 动态透明度与边框效果 五、总结…