C++语法系列之特殊类设计

article/2025/6/10 5:35:40

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

其实就是防止拷贝构造和赋值运算符的重载,这个在C++11中讲了,在C++98之前可以声明为private,现在直接等于delete就可以了

//C++98
class A {
public:A(){}
private:A(const A& a);A& operator=(const A& a);
};
class A {
public:A() {}A(const A& a) = delete;A& operator=(const A& a) = delete;
};

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

实现方式:
第一种:

  1. 将类的构造函数私有,拷贝构造关掉。防止别人调用拷贝在栈上生成对象。
  2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建,一定是静态的奥,只有静态才可以::访问

第二种:

将析构函数设置成私有,这样普通对象无法创建,new出来的对象只有delete了才会去调析构函数,那我们可以额外开一个函数来析构。
但是这样是不还有问题啊,HeapOnly *a1 = a3;这样a1是不还在栈上啊,所以这个是伪的,因为有构造函数才会new,构造函数关不了,所以不稳妥。

所以第一种是最稳妥的,把所有方式都关了。
第一种方法:原理简单说一下:create()函数调用new,new需要调用operator new + 构造函数,构造函数是私有,类内可见,所以就可以创建对象了

class HeapOnly {public:void Destroy() {delete this;}static HeapOnly* create(){return new HeapOnly;}
private://~HeapOnly() {}HeapOnly() {}HeapOnly(const HeapOnly& p) = delete;HeapOnly& operator=(const HeapOnly& p) = delete;
};
int main()
{HeapOnly* a3 = HeapOnly:: create();return 0;
}

第二种方法:

class HeapOnly {public:void Destroy() {delete this;}
private:~HeapOnly() {}
};
int main()
{//HeapOnly a;HeapOnly *a1 = new HeapOnly;//static HeapOnly a2;//delete a1;a1->Destroy();
}

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

方法:和上面的类似
实现方式:

  1. 将类的构造函数私有,拷贝构造声明成私有。关掉operator new,因为拷贝构造不能关,返回一个静态的成员调用的就是拷贝构造,但是这样还得防止new一个对象,所以只能关operator new
  2. 提供一个静态的成员函数,在该静态成员函数中完成栈对象的创建,一定是静态的奥,只有静态才可以::访问
class StackOnly {public:static StackOnly CreateStack(){StackOnly a;return  a;}void* operator new(size_t size) = delete;
private:StackOnly(){}//StackOnly(const StackOnly& p) = delete;//StackOnly& operator=(const StackOnly& p) = delete;
};int main()
{StackOnly a1 = StackOnly::CreateStack();StackOnly a1 = StackOnly::CreateStack();//static StackOnly a3;//StackOnly* p = new StackOnly(a1);//StackOnly* p3 = new StackOnly(a1);//p3仍在堆上return 0;
}

有一点问题,还是防止不了在静态区创建对象
static StackOnly a1 = StackOnly::CreateStack();

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

C++98之前就是把构造函数私有,这样继承的时候无法调用基类的构造函数,就会无法继承(只是创建不了对象,在继承的时候不会报错)

C++11后利用final关键字直接更简洁

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

这种会直接报错

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

什么是单例模式呢?
在这里插入图片描述
特点:
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置
息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
实现:
错误思路(不正确,但是可以实现效果)

class Singleton
{
private:static int p;
public:Singleton(){assert(p > 0);p--;}Singleton(const Singleton& p) = delete;Singleton& operator=(const Singleton& p) = delete;
};
int Singleton::p = 1;

就是存一个static变量p,在调用构造函数的时候去–,这样第二次就无法创建对象了,但是这样如果写两个对象,程序直接由于断言就崩了,所以这样写不对,也别去学。(属于是胡思乱想的结果罢了)

实现

先说一下大体的思路,你构造函数和赋值一定要关的,这没啥说的,构造函数私有,提供一个返回单例对象的接口,但是你构造函数关了,所以要搞一个静态私有成员,访问对象时只通过这个接口来访问,只有一个对象
单例模式有两种实现模式:1、饿汉模式:不管你用不用,程序启动时就创建一个唯一的实例对象
实现:

class Singleton {
public://提供一个创建单例对象的函数static Singleton& getInstance(){return _sinst;}void add(const pair<int, int>& p){mp[p.first] = p.second;}void Print(){for (const auto& p : mp){cout << p.first << ' ' << p.second << endl;}}
private:Singleton() {}static Singleton _sinst;Singleton& operator=(const Singleton& p) = delete;Singleton(const Singleton& p) = delete;map<int, int> mp;
};
Singleton Singleton::_sinst;

优点:简单
缺点:可能会导致进程启动慢(比如要初始化很多东西),且如果有多个单例类对象实例启动顺序不确定(如果一个类依靠另一个类来初始化,启动顺序还不确定,就不好)。
2.懒汉模式
如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。
怎么实现呢?和上面的类似,只不过我存一个指针,在调用这个函数的时候再初始化,这样就不会不用也创建对象了。

	class Singleton {public://提供一个创建单例对象的函数static Singleton& getInstance(){if (_sinst == nullptr){//第一次调用这个函数时才创建单例对象_sinst = new Singleton;}return *_sinst;}void add(const pair<string, string>& p){mp[p.first] = p.second;}void Print(){for (const auto& p : mp){cout << p.first << ' ' << p.second << endl;}}private:Singleton() {}static Singleton* _sinst;Singleton& operator=(const Singleton& p) = delete;Singleton(const Singleton& p) = delete;map<string, string> mp;};Singleton* Singleton::_sinst = nullptr;

到这就完事了吗?当然没有,你new出来的对象当然要析构啊,这里再推荐两种方式(析构函数一定不行,因为你实例化的对象是个函数接口,生命周期结束不会自动调用析构函数)
1.搞一个del函数,注意要搞成静态的,不然没法访问,但是这样需要主动调用,我不想主动调用怎么办,请看下一个方法

static void Del()
{if (_sinst != nullptr){delete _sinst;_sinst = nullptr;}
}

2.在加一个类,该类的析构函数调用Del()

class GC {
public:~GC(){Singleton::getInstance().Del();}
};
GC gc;

这样生命周期结束时就会调用Del();

还可以这样搞一个

	class GC {public:~GC(){lazy::Singleton::getInstance().Del();cout << "GC" << endl;}};static GC _gc;

他分装在单例类的内部(记得要初始化)(Singleton* Singleton::_sinst = nullptr;)
原理类似,静态成员一直存在,结束调用这个类的析构,这样既可以做到如果我不希望中间某个时候析构,让他自己生命周期结束可以析构,也可以我如果不想用了直接主动的调用析构(del())。

总结

本次内容不难,如果看着很费劲建议去多学学构造函数,拷贝构造函数,普通对象和new出来的对象,new的原理啊等等,这些东西掌握了,以上内容还是很好理解的。


http://www.hkcw.cn/article/XilyxbEUKq.shtml

相关文章

网络安全厂商F5推出AI Gateway,化解大模型应用风险

AI正以前所未见的速度重塑数字化体验。然而&#xff0c;企业在加速落地现代化数字体验的过程中&#xff0c;其在保障和交付AI应用方面仍面临严峻挑战。这些应用需处理海量数据&#xff0c;涉及复杂流量模式&#xff0c;并引入更高级的安全威胁&#xff0c;而企业当前的安全能力…

调用.net DLL让CANoe自动识别串口号

1.前言 CANoe9.0用CAPL控制数控电源_canoe读取程控电源电流值-CSDN博客 之前做CAPL通过串口控制数控电源&#xff0c;存在一个缺点&#xff1a;更换电脑需要改串口号 CSDN上有类似的博客&#xff0c;不过要收费&#xff0c;本文根据VID和PID来自动获取串口号&#xff0c;代码…

C++中锁与原子操作的区别及取舍策略

文章目录 锁与原子操作的基本概念锁&#xff08;Lock&#xff09;原子操作&#xff08;Atomic Operations&#xff09; 锁与原子操作的区别1. **功能**2. **性能**3. **复杂性**4. **适用场景** 锁与原子操作的取舍策略1. **简单变量操作**2. **复杂共享资源**3. **性能敏感场景…

知识拓展卡———————RSTP与MSTP的简要说明

我们在之前的学习过程中了解了STP&#xff08;生成树协议&#xff09;的各个端口角色选举的相关概念&#xff0c;今天我们再来拓展一下关于STP的扩展性知识点MSTP与RSTP。 目录 RSTP&#xff08;Rapid Spanning Tree Protocol,快速生成树协议&#xff09;: 端口角色&#xf…

NSSCTF [LitCTF 2025]test_your_nc

[复现]绕过学的还是太差了&#xff0c;多积累吧 ​​​​​​题目 题目: 给了一个python文件 #!/bin/python3 import osprint("input your command")blacklist [cat,ls, ,cd,echo,<,${IFS},sh,\\]while True:command input()for i in blacklist:if i in com…

(10)Fiddler抓包-Fiddler如何设置捕获Firefox浏览器的Https会话

1.简介 经过上一篇对Fiddler的配置后&#xff0c;绝大多数的Https的会话&#xff0c;我们可以成功捕获抓取到&#xff0c;但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话&#xff0c;需要我们更进一步的配置才能捕获到会话进行抓包。 2.环境 1.环境是Windows 10版…

持续领跑中国异地组网路由器市场,贝锐蒲公英再次登顶销量榜首

作为国产远程连接SaaS服务的创领者&#xff0c;贝锐持续引领行业发展&#xff0c;旗下贝锐蒲公英异地组网路由器&#xff0c;凭借出色的技术实力和市场表现&#xff0c;斩获2024年线上电商平台市场销量份额中国第一的佳绩&#xff0c;充分彰显了其在网络解决方案与异地组网领域…

Redis底层数据结构之深入理解跳表(2)

上一篇文章中我们详细讲述了跳表的增添、查找和修改的操作&#xff0c;这篇文章我们来讲解一下跳表在多线程并发时的安全问题。在Redis中&#xff0c;除了网络IO部分和大文件的后台复制涉及到多线程外&#xff0c;其余任务执行时全部都是单线程&#xff0c;这也就意味着在Redis…

振动力学:有阻尼单自由度系统(简谐力激励的受迫振动)

本文讨论外力作用下的单自由度系统的受迫振动&#xff0c;特别是详细讨论了系统的共振特性。 1. 受迫振动的解及其组成 根据文章1和2的描述&#xff0c;此时简谐力外力 f ( t ) f 0 sin ⁡ ( ω t ) f(t) f_0 \sin(\omega t) f(t)f0​sin(ωt)。因此振动方程为&#xff1a;…

Vert.x学习笔记-EventLoop与Handler的关系

Vert.x学习笔记 一、底层机制&#xff1a;事件驱动的核心引擎二、协作流程&#xff1a;事件分发与执行三、线程安全&#xff1a;EventLoop与Handler的约束四、性能优化&#xff1a;最佳实践与注意事项五、典型场景与架构设计六、总结 在Vert.x中&#xff0c;**EventLoop&#x…

DevEco Studio的使用

IDE环境的搭建 快速开始 因为本版本的DevEco Studio为一体化版本&#xff0c;已经包含了SDK&#xff0c;构建插件&#xff0c;ohpm等工具&#xff0c;所以您 在安装完成后即可开箱即用&#xff0c;进行工程开发&#xff0c;无需配置环境。首先看一下安装DevEco Studio的相关流…

手动删除网页上的禁止复制事件

以Edge浏览器为环境、以网络上一个文档为例。 右击页面&#xff0c;打开【检查】工具。选择元素&#xff0c;打开【事件侦听器】&#xff1a; 展开copy&#xff0c;删除里面的事件&#xff1a; 选中文字&#xff0c;进行复制

【MATLAB去噪算法】基于CEEMD联合小波阈值去噪算法(第三期)

02.去噪算法原理 1.引言 传统EMD方法存在模态混叠问题&#xff0c;即信号成分在不同IMF分量中出现碎片化分布。为改进这一问题&#xff0c;Huang等&#xff08;1999&#xff09;提出间歇性测试算法&#xff0c;但效果有限。Wu和Huang&#xff08;2009&#xff09;发展的集合经…

Semi-Supervised Neuron Segmentation via Reinforced Consistency Learning

perturbed counterpart x u ′ ^{u} u′ waterz环境不好满足&#xff0c;不建议复现

R语言使用随机过采样(Random Oversampling)平衡数据集

随机过采样&#xff08;Random Oversampling&#xff09;是一种用于平衡数据集的技术&#xff0c;常用于机器学习中处理类别不平衡问题。当某个类别的样本数量远少于其他类别时&#xff08;例如二分类中的正负样本比例悬殊&#xff09;&#xff0c;模型可能会偏向多数类&#x…

pcie 日常问答-20250528

问题均来自工作总结&#xff0c;面经问题&#xff1b;多为发散性问题&#xff1b;大多均会结合S IP rtl实现进行细致分析。 1. dllp包有哪些类型&#xff1f;dllp主要功能是干甚呢的&#xff1f; dllp是一个点到点的传输&#xff08;传输过程中没有任何标识&#xff09;&#…

ADK实战-基于ollama+qwen3实现外部工具串行调用

0 环境准备 1 开发环境准备 1.1 创建项目python环境 1.2 在pycharm创建项目 1.3 安装项目依赖 2 资源准备 3 adk agent构建 3.1 新建adk_agent_tool_serial python包 3.2 编辑__init__.py文件 4 配置env 4.1 新建.env文件 4.2 编辑.env文件 5 agent逻辑实现 5.1 …

降本增效的新引擎:GEO如何提升企业营销ROI

在当前经济环境下&#xff0c;企业面临着前所未有的成本压力和效率挑战。深耕数字营销二十余年&#xff0c;我们见证了从传统广告到数字营销&#xff0c;再到如今生成式AI时代的每一次效率变革。在这个新阶段&#xff0c;生成式引擎优化&#xff08;GEO&#xff09;正在成为企业…

Blinko智能笔记系统实现跨平台同步与隐私保护的完整技术方案解析

文章目录 前言1. Docker Compose一键安装2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 推荐 ​ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站 前言 是否…

OpenCV CUDA模块特征检测------创建Harris角点检测器的GPU实现接口cv::cuda::createHarrisCorner

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数创建一个 基于 Harris 算法的角点响应计算对象&#xff0c;专门用于在 GPU 上进行高效计算。 它返回的是一个 cv::Ptrcv::cuda::Cornernes…