特殊类设计

文章目录

  • 特殊类设计
    • 1. 请设计一个类,不能被拷贝
    • 2. 请设计一个类,只能在堆上创建对象
    • 3. 请设计一个类,只能在栈上创建对象
    • 4. 请设计一个类,不能被继承
    • 5. 单例模式
      • 5.1 设计模式
      • 5.2 单例模式
        • (1) 饿汉模式
        • (2) 懒汉模式

特殊类设计

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

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

  • C++98
    将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可。
class CopyBan
{
// ...
private:CopyBan(const CopyBan&);CopyBan& operator=(const CopyBan&);
//...
}

原因:

  1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不能禁止拷贝了

  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了。

  • C++11
    C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。
class CopyBan
{
// ...CopyBan(const CopyBan&)=delete;CopyBan& operator=(const CopyBan&)=delete;
//...
};

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

  • 思路1:析构函数私有化
class HeapOnly
{
public:void Destroy(){delete this;}
private:~HeapOnly(){}
};

提供一个Destroy()函数直接delete this释放对象,我们使用完对象后只需要显示调用Destroy()函数

在这里插入图片描述

  • 思路2: 构造函数私有化

实现方式:

  1. 将类的构造函数私有,拷贝构造和赋值重载声明成私有。防止别人调用拷贝在栈上生成对象。(比如这种情况:HeapOnly p2(*p);)
  2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建。(此函数必须声明为static的,否则无法调用此函数,调用此函数需要对象,对象是此函数new出来的,典型的”鸡生蛋,蛋生鸡“的问题,所以必须声明为静态的)
class HeapOnly
{
public:static HeapOnly* CreatObj(){HeapOnly* p = new HeapOnly;return p;}
private:HeapOnly(){}HeapOnly(const HeapOnly&) = delete;HeapOnly& operator=(const HeapOnly&) = delete;
};

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

思路:同上将构造函数私有化,然后设计静态方法创建对象返回即可。

class StackOnly
{
public:static StackOnly CreateObj(int x=0){return StackOnly(x);      // 返回的是拷贝}// 走移动构造StackOnly(const StackOnly&& st):_x(st._x){}
private:StackOnly(int x=0):_x(x){}StackOnly(const StackOnly&st) = delete;int _x;
};
  • 单纯的封住构造函数,不能避免 static StackOnly t3 = t1;情况,所以我们也要把拷贝构造封死。

  • 但是CreateObj函数返回的就是临时对象的拷贝,一旦直接封死拷贝构造函数,也无法通过CreateObj创建对象。StackOnly(x)是右值,我们可以提供一个移动构造函数来解决

int main()
{StackOnly t1=StackOnly::CreateObj(1);//static StackOnly t3 = t1;    err
}

4. 请设计一个类,不能被继承

  • C++98方式:构造函数私有化,派生类中调不到基类的构造函数。则无法继承
class NonInherit
{
public:static NonInherit CreateObj(){return NonInherit();}
private:NonInherit(){}
};
  • C++11方法
    final关键字, final修饰类,表示该类不能被继承
class A final
{// ....
};

5. 单例模式

5.1 设计模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。为什么会产生设计模式这样的东西呢?就像人类历史发展会产生兵法。最开始部落之间打仗时都是人拼人的对砍。后来春秋战国时期,七国之间经常打仗,就发现打仗也是有套路的,后来孙子就总结出了《孙子兵法》。孙子兵法也是类似。
使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

5.2 单例模式

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

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

(1) 饿汉模式

一开始(main函数之前)就创建对象

class Singleton
{
public:static Singleton*GetInstance(){return _ins;}
private:// 限制类外面随意创建对象Singleton(){cout << "Singleton()" << endl;}Singleton(const Singleton& s) = delete;Singleton& operator=(const Singleton& s) = delete;private:static Singleton* _ins;
};
Singleton* Singleton::_ins = new Singleton;  // 在程序入口之前就完成单例对象的初始化

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

饿汉模式的分析:

  • 缺点:

    • 如果单例对象初始化很慢(如初始化动作多,还会伴随一些IO行为,如读配置文件等),main函数之前就要申请,会出现2个问题:<1> 暂时不需要使用却占用资源 <2> 程序启动会受到影响
    • 如果两个单例都是饿汉,并且有依赖关系,要求单例1再创建,单例2再创建,饿汉无法控制顺序,懒汉才可以
  • 优点:

    • 简单(相对懒汉而言)
(2) 懒汉模式

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

class Singleton
{
public:static Singleton* GetInstance(){// 双检查加锁if (_ins == nullptr)    // 提高效率,不需要每次获取单例都加锁解锁{_imtx.lock();if (_ins == nullptr) // 保证线程安全和只new一次{_ins = new Singleton;}_imtx.unlock();}return _ins;}// 一般全局都要使用单例对象,所以单例对象一般不需要显示释放// 有些特殊场景,想显示释放一下static void DelInstance(){_imtx.lock();if (_ins){delete _ins;_ins = nullptr;}_imtx.unlock();}// 内部类: 单例回收class GC{public:~GC(){DelInstance();}};//	定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象static GC _gc;private:// 限制类外面随意创建对象Singleton(){}Singleton(const Singleton& s) = delete;Singleton& operator=(const Singleton& s) = delete;private:static Singleton* _ins;static mutex _imtx;
};
Singleton* Singleton::_ins = nullptr;
mutex Singleton::_imtx;   // 锁这里不用给值, 直接定义即可
Singleton::GC Singleton::_gc;

懒汉模式分析:

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

实现懒汉的另一种方式:

在C++11标准中,要求局部静态变量初始化具有线程安全性,所以我们可以很容易实现一个线程安全的单例类。

class Singleton
{
public:// C++11之前: 这里不能保证初始化静态对象的线程安全问题// C++11之后: 这里可以保证初始化静态对象的线程安全问题static Singleton* GetInstance(){static Singleton ins;return &ins;}// 一般全局都要使用单例对象,所以单例对象一般不需要显示释放// 有些特殊场景,想显示释放一下static void DelInstance(){_imtx.lock();if (_ins){delete _ins;_ins = nullptr;}_imtx.unlock();}// 内部类: 单例回收class GC{public:~GC(){DelInstance();}};//	定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象static GC _gc;private:// 限制类外面随意创建对象Singleton(){}Singleton(const Singleton& s) = delete;Singleton& operator=(const Singleton& s) = delete;private:static Singleton* _ins;static mutex _imtx;
};
Singleton* Singleton::_ins = nullptr;
mutex Singleton::_imtx;
Singleton::GC Singleton::_gc;

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

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

相关文章

python如何创建自己的对冲交易算法

在这篇文章中&#xff0c;我解释了如何创建一个人工智能来每天为我进行自动交易。 随着机器学习的现代进步和在线数据的轻松访问&#xff0c;参与量化交易变得前所未有的容易。为了让事情变得更好&#xff0c;AWS 等云工具可以轻松地将交易想法转化为真正的、功能齐全的交易机器…

UDP网络通信反复发收

package UDP2;import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.util.Scanner;/* * 完成UDP 通信快速入门 实现发1收1*/ public class Client {public static void main(String[] args) throws Exception{// …

k8s的coreDNS添加自定义hosts

1.ack的hosts不会继承宿主机的hosts&#xff0c;而工作中有一个域名默认是走内网解析&#xff0c;内网被限制访问了&#xff0c;只能在coreDNS中加一个hosts解析域名 2.编辑configmap (coredns) kubectl edit configmap -n kube-system coredns 增加hosts节点 Corefile: |.:53…

VMware Workstation安装ESXi和vCenter(8.0)

一、环境准备 虚拟机&#xff1a;VMware Workstation 17 Pro ESXi&#xff1a;ESXi-8.0U2-22380479-standard vCenter&#xff1a;VMware-VCSA-all-8.0.2-22385739.iso 主要是内存设置&#xff0c;因为vCenter需要14Gb内存&#xff0c;所以这个至少16Gb。 硬盘需要2块&…

S4.2.4.3 Electrical Idle Sequence(EIOS)

一 本章节主讲知识点 1.1 EIOS的具体码型 1.2 EIOS的识别规则 1.3 EIEOS的具体码型 二 本章节原文翻译 当某种状态下&#xff0c;发送器想要进入电器空闲状态的时候&#xff0c;发送器必须发送EIOSQ&#xff0c;也既是&#xff1a;电器Electrical Idle Odered Set Sequenc…

Flink部署模式及核心概念

一.部署模式 1.1会话模式&#xff08;Session Mode&#xff09; 需要先启动一个 Flink 集群&#xff0c;保持一个会话&#xff0c;所有提交的作业都会运行在此集群上&#xff0c;且启动时所需的资源以确定&#xff0c;无法更改&#xff0c;所以所有已提交的作业都会竞争集群中…

SpringBoot+Vue实现AOP系统日志功能

AOP扫盲&#xff1a;Spring AOP (面向切面编程&#xff09;原理与代理模式—实例演示 logs表&#xff1a; CREATE TABLE logs (id int(11) NOT NULL AUTO_INCREMENT,operation varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 操作名称,type varchar(255) COLL…

【剑指Offer】36.二叉搜索树与双向链表

题目 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表。如下图所示 数据范围&#xff1a;输入二叉树的节点数 0≤n≤1000&#xff0c;二叉树中每个节点的值 0≤val≤1000 要求&#xff1a;O(1)&#xff08;即在原树上操作&#xff09;&#xff0c;时间…

【网络】对于我前面UDP博客的补充

UDP 前言正式开始UDP报文UDP报文如何将UDP报文和报头进行分离和封装UDP如何将有效载荷交付给上层如何提取出完整报文报头是啥报头中的检验和 UDP的特点IO接口乱序问题UDP是全双工的注意事项基于UDP的应用层协议 再次谈论端口五元组端口号范围划分netstatxargs 前言 本篇比较偏…

技术文档工具『Writerside』抢鲜体验

前言 2023 年 10 月 16 日&#xff0c;JetBrains 宣布以早期访问状态推出 Writerside&#xff0c;基于 IntelliJ 平台的 JetBrains IDE&#xff0c;开发人员可使用它编写、构建、测试和发布技术文档&#xff0c;可以作为 JetBrains IDE 中的插件使用&#xff0c;也可以作为独立…

高防CDN的发展趋势

随着互联网的迅速发展&#xff0c;网站和在线服务的安全性变得至关重要。网络攻击如DDoS攻击和恶意流量正在增加&#xff0c;因此高防CDN&#xff08;高防御内容分发网络&#xff09;成为网络安全的重要组成部分。本文将探讨高防CDN未来的发展趋势&#xff0c;并比较其与传统CD…

laravel队列

laravel redis队列 1、创建job队列任务 php artisan make:job StoreUser执行上述命令后&#xff0c;会生成app/Jobs/StoreUser.php文件&#xff0c;编辑文件内容如下&#xff1a; <?phpnamespace App\Jobs;use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queu…

leetcode:231. 2 的幂(位运算)

一、题目&#xff1a; 函数原型&#xff1a;bool isPowerOfTwo(int n) 二、思路&#xff1a; 根据题意&#xff0c;要判断一个数是否为2的幂。如果一个数是2的幂&#xff0c;那么该数的二进制表示中只有一个1。所以只需要将该数的二进制表示中的最低位1移除&#xff0c;判断剩下…

三十七、【进阶】SQL的explain

1、explain 2、基础使用 在使用explain关键字时&#xff0c;只需要在所执行语句前加上explain即可 mysql> explain select * from stu where id3; ---------------------------------------------------------------------------------------------------------- | id | s…

2023网络安全工程师面试题汇总(附答案)

一、面试开场白 一般首先是一段例行的开场自&#xff08;说&#xff09;我&#xff08;学&#xff09;介&#xff08;逗&#xff09;绍&#xff08;唱&#xff09;&#xff0c;在这里我直接给你个万能公式&#xff1a; 1、在xx安全论坛投稿过xx篇文章&#xff0c;获得xx元稿费…

中文编程开发语言工具构件说明:屏幕截取构件的编程操作

屏幕截取 用于截取指定区域的图像。 图 标&#xff1a; 构件类型&#xff1a;不可视 重要属性 l 截取类型 枚举型&#xff0c;设置在截取屏幕时的截取类型。包括&#xff1a;全屏幕、指定区域、活动窗口三种。当全屏幕截取时相当于执行了硬拷屏&#xff08;PrintScre…

HVV(护网)蓝队视角的技战法分析

一、背景 1.HVV行动简介 HVV行动是国家应对网络安全问题所做的重要布局之一。从2016年开始&#xff0c;随着我国对网络安全的重视&#xff0c;演习规模不断扩大&#xff0c;越来越多的单位都加入到HVV行动中&#xff0c;网络安全对抗演练越来越贴近实际情况&#xff0c;各机构…

php 数组基础/练习

数组 练习在最后 数组概述 概述与定义 数组中存储键值对 数组实际上是一个有序映射 key-value&#xff0c;可将其当成真正的数组、列表&#xff08;向量&#xff09;、散列表、字典、集合、栈、队列等 数组中的元素可以是任意类型的数据对象&#xff08;可以嵌套数组&#…

英语什么时候加s和es

名词变复数一般情况下加s&#xff0c;以s,x,ch,sh结尾加es。一个名词如果表示一个或一样东西&#xff0c;它取单数形式&#xff0c;如果表示两个或更多的这类东西&#xff0c;则需要用名词复数形式。 1 以s,x,sh,ch结尾的词&#xff0c;加es。 2 以辅音字母&#xff08;除a/e/…

CNN系列

文章目录 R-CNN&#xff08;2014&#xff09;Conclusion SPP-net&#xff08;2015&#xff09; R-CNN&#xff08;2014&#xff09; 哈哈 创新&#xff1a; (1)人们可以将高容量卷积神经网络(cnn)应用于自下而上的区域建议&#xff0c;以定位和分割对象; (2)当标记训练数据稀缺…