特殊类的设计----《Hello C++ Wrold!》(28)--(C/C++)

特殊类的设计----《Hello C++ Wrold!》(28)--(C/C++)

文章目录

前言

在 C++ 面向对象编程体系中,类是封装数据与行为的核心单元,其设计直接关系到程序的安全性、可维护性与性能表现。除了支撑常规业务逻辑的普通类,实际开发中常需面对具有特殊约束的场景:例如防止对象拷贝以规避资源重复释放风险,限定对象创建位置(仅堆或仅栈)以规范内存管理,禁止类被继承以保障核心逻辑不被篡改,或是确保类仅存在一个实例以实现全局资源统一调度 —— 这些需求的实现,正是特殊类设计的核心范畴。​

本文聚焦 “特殊类设计” 这一主题,系统拆解五种典型特殊类的实现逻辑与技术细节。从 “不能被拷贝的类” 对拷贝构造函数、赋值运算符的管控,到 “只能在堆 / 栈上创建对象的类” 对构造函数与内存分配接口的限制;从 “不能被继承的类” 基于构造函数私有化(C++98)与final关键字(C++11)的两种实现,到 “单例模式(仅一个对象的类)” 的饿汉模式与懒汉模式对比,每类设计均结合 C++ 语言特性,提供完整代码示例,并深入分析方案的优缺点与适用场景。​

无论是 C++ 学习者进阶理解类的设计边界,还是开发人员解决实际项目中的特殊类需求,本文都将通过清晰的原理讲解与实用的技术指引,助力读者掌握特殊类设计的核心思路,提升代码设计的严谨性与专业性。

设计一个不能被拷贝的类

只需让该类不能调用拷贝构造函数以及赋值运算符重载即可
C++98的方法: 将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有 C++11的方法: 用delete禁止生成拷贝构造函数和赋值运算符重载的默认成员函数 

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

方法:

让这个类不能被拷贝并且构造函数设置成私有的

然后再提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建
实现举例:classHeapOnly{public:static HeapOnly*CreateObj(){returnnew HeapOnly;}private:HeapOnly(){//...}HeapOnly(const HeapOnly& hp)=delete; HeapOnly&operator=(const HeapOnly& hp)=delete;};

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

方法:先把构造函数私有化 并且禁用operator new

然后再搞个静态成员函数去构造对象就行了(不搞成静态的话,没对象的时候调用不了)

–这里构造函数私有化的意义:防止外面eg: new A()这样
实现举例:classStackOnly{public:static StackOnly CreateObj(){ StackOnly st;return st;}private:StackOnly(){//...}void*operatornew(size_t size)=delete;};
引申:关于这里的operator new,这个的话默认调用的是全局的new,这类里面这样搞了之后这个类就用不了new

设计一个不能被继承的类

方法:

第一种:(C++98的方法):让构造函数私有化就行了

第二种(C++11的方法):用final关键字

设计一个只能创建一个对象的类(也叫做单例模式)

单例模式的概念:就是一个类只能创建一个对象

作用:该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享

单例模式的两种实现方法

饿汉模式

这个模式的优缺点:

优点:实现起来简单

缺点:1、如果单例对象初始化内容很多,影响启动速度
2、如果两个单例类,互相有依赖关系,这时候对实例化的顺序有要求–但是饿汉模式控制不了实例化的顺序(尤其是在不同的编译单元)

namespace hungry {classSingleton{public:static Singleton&GetInstance(){return _sinst;}private:Singleton(){// ...}//这里是防拷贝,自己演示的是C++11的方式Singleton(const Singleton& s)=delete; Singleton&operator=(const Singleton& s)=delete;static Singleton _sinst;}; Singleton Singleton::_sinst;

懒汉模式

在这里插入图片描述
namespace lazy {classSingleton{public:static Singleton&GetInstance(){if(_psinst ==nullptr){ _psinst =new Singleton;}return*_psinst;}staticvoidDelInstance(){if(_psinst){delete _psinst; _psinst =nullptr;}}classtmp{public:~tmp(){ lazy::Singleton::DelInstance();}};private:Singleton(){// ...}// 防拷贝Singleton(const Singleton& s)=delete; Singleton&operator=(const Singleton& s)=delete;static Singleton* _psinst;static tmp _tmp;}; Singleton* Singleton::_psinst =nullptr;//这意味着程序启动时,单例对象并没有被创建,仅仅是定义了一个指向它的空指针。 Singleton::tmp Singleton::_tmp;}
在这里插入图片描述
一般单例不需要释放:因为程序结束的时候,操作系统会自动去回收的(用的不是析构函数)

除非特殊场景:

1.中途需要显示释放 2.程序结束时,需要做一些特殊动作(比如持久化)

这里的第二种情况的持久化就是需要在程序结束时将数据写入其他地方–这个时候就需要调用析构函数,用析构函数写入–tmp就保证了他的析构函数会起作用

Read more

【C++经典例题】反转字符串中单词的字符顺序:两种实现方法详解

【C++经典例题】反转字符串中单词的字符顺序:两种实现方法详解

💓 博客主页:倔强的石头的ZEEKLOG主页             📝Gitee主页:倔强的石头的gitee主页             ⏩ 文章专栏:C++经典例题                                   期待您的关注   目录 问题描述 基于快慢指针的解法 基于索引的解法 两种方法的比较   问题描述 在处理字符串相关的问题时,反转字符串中每个单词的字符顺序是一个常见的任务,同时要保证空格和单词的初始顺序不变。   给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。 * s 包含可打印的 ASCII 字符。 * s 不包含任何开头或结尾空格。 * s 里 至少 有一个词。 * s 中的所有单词都用一个空格隔开。 原题链接:557. 反转字符串中的单词 III - 力扣(LeetCode) 下面我们将详细介绍两种解决该问题的方法,包括其解题思路和具体实现细节。   基于快慢指针的解法 1. 解题思路 快慢指针是一种常用的技巧

By Ne0inhk
【Trae】如何使用Trae编译C++(附带MinGW)

【Trae】如何使用Trae编译C++(附带MinGW)

结果 先看结果 这是一道回文串题目,F5编译,控制台输入输出。 下载 * 下载Trae编译器,直接去官网下:https://www.trae.cn/ * 下载VSCode编译器,这个相信用Trae的各位都不陌生。https://code.visualstudio.com/ * 查看你的C盘,C:\Users\Administrator\.vscode\extensions路径下是否有extensions.json文件,如果没有,请将VSCode卸载后重装。 安装插件 在VSCode里安装“C/C++”插件。 这里需要在VSCode里安装的原因是C/C++插件在Trae里是搜不到的。 再次查看C:\Users\Administrator\.vscode\extensions路径,看看插件是否安装成功,且extensions.json文件里有这个插件。 关闭VSCode,打开Trae。 点击右上角头像-IDE设置 选择“从VSCode导入”,等待它导入插件,导入完成后点击查看一下,

By Ne0inhk
C++:set/multiset和map/multimap文档详细解析

C++:set/multiset和map/multimap文档详细解析

Hello大家好! 很高兴与大家见面! 给生活添点快乐,开始今天的编程之路。 我的博客:<但愿. 我的专栏:C语言、题目精讲、算法与数据结构、C++ 欢迎点赞,关注 目录   前言   一 容器的分类(根据容器中各个数据之间的关系)          1.1序列式容器                  1.1.1序列式容器的概念                  1.1.2序列式容器的例子           1.2关联式容器                  1.2.1关联式容器的概念                  1.2.2关联式容器的例子   二  set/multiset           2.1参考文档(multiset包在set中所以其没有头文件)           2.2set类的介绍                   2.2.1set类的实现的简单介绍                  2.2.2set类的接口介绍                           2.

By Ne0inhk
【C++】深入解析AVL树:平衡搜索树的核心概念与实现

【C++】深入解析AVL树:平衡搜索树的核心概念与实现

【C++】深入解析AVL树:平衡搜索树的核心概念与实现 * 摘要 * 目录 * 一、AVL树的概念 * 二、AVL树的模拟实现 * 1. 节点结构体和树的类模板 * 2. 平衡因子的概念和实现 * 3. 插入 * 4. 旋转操作 * 4.1 右单旋 * 4.2 左单旋 * 4.3 左右双旋 * 4.4 右左双旋 * 三、AVL树的平衡检测 * 总结 摘要 本文深入解析了AVL树的核心概念与实现,包括节点结构设计、平衡因子定义及其更新机制、插入操作的自下而上平衡调整策略,以及四种旋转方式(左单旋、右单旋、左右双旋、右左双旋)对保持树平衡的重要作用。同时,提供了AVL树高度计算与平衡检测的实现方法,确保每个节点的平衡因子正确维护,从而保证树在插入操作后的高效性与稳定性。通过本文内容,读者可以系统掌握AVL树的原理、实现与调试技巧,

By Ne0inhk