【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
阅读导航
- 引言
- 一、特殊类 --- 不能被拷贝的类
- 1. C++98方式:
- 2. C++11方式:
- 二、特殊类 --- 只能在堆上创建对象的类
- 三、特殊类 --- 只能在栈上创建对象的类
- 四、特殊类 --- 不能被继承的类
- 1. C++98方式
- 2. C++11方法
- 总结
- 温馨提示
引言
在面向对象编程中,特殊类是指具有不同于常规类的特殊属性或限制的类。这些类可以通过各种方式达到特定的目标和需求,例如只能在堆 ( 栈 ) 上创建对象的类、禁止拷贝和继承等。
本文将会讨论四种常见的特殊类:不能被拷贝的类、只能在堆上创建对象的类、只能在栈上创建对象的类以及不能被继承的类。我们将介绍它们的实现方法和应用场景,并提供相应的代码示例以帮助读者更好地理解这些特殊类的概念和用法。
一、特殊类 — 不能被拷贝的类
当一个类的拷贝是不允许的,可以采取以下两种方式来实现:
1. C++98方式:
在C++98中,可以通过将拷贝构造函数和赋值运算符重载声明为私有,并且不实现它们来禁止拷贝。这样做的原因是私有访问权限限制了类外部的代码无法访问这两个函数的实现。
class CopyBan {
private:CopyBan(const CopyBan&); // 声明拷贝构造函数为私有CopyBan& operator=(const CopyBan&); // 声明赋值运算符重载为私有
public:// 其他公共成员函数和数据成员
};
这种方式通过将拷贝构造函数和赋值运算符重载放在私有区域,从而阻止了类的外部对象调用这两个函数,实现了禁止拷贝的目的。
2. C++11方式:
在C++11中,可以使用delete
关键字来删除拷贝构造函数和赋值运算符重载。通过在函数声明后加上= delete
,可以明确告诉编译器要删除此函数,防止类外部的代码调用它。
class CopyBan {
public:CopyBan(const CopyBan&) = delete; // 删除拷贝构造函数CopyBan& operator=(const CopyBan&) = delete; // 删除赋值运算符重载// 其他公共成员函数和数据成员
};
这种方式更加简洁明了,直观地表达了禁止拷贝的意图。使用= delete
语法可以方便地阻止拷贝构造函数和赋值运算符重载的调用。
无论是C++98还是C++11,这两种方式都能有效地禁止类的拷贝,增强代码的稳定性和安全性。选择哪种方式取决于你使用的C++版本和个人偏好。
二、特殊类 — 只能在堆上创建对象的类
要设计一个只能在堆上创建对象的类,可以使用私有的析构函数和静态成员函数来实现:
class HeapOnly {
private:HeapOnly() {} // 私有的默认构造函数,防止在栈上创建对象~HeapOnly() {} // 私有的析构函数,防止在栈上销毁对象public:static HeapOnly* createInstance() {return new HeapOnly();}void destroyInstance() {delete this;}
};
这个类中,私有的默认构造函数和析构函数阻止了在栈上创建和销毁对象。而通过静态的createInstance()
函数,可以在堆上创建该类的对象,并返回指向该对象的指针。然后,我们可以使用对象的destroyInstance()
函数在适当的时候手动删除对象,从而释放内存。
以下是示例代码的使用方式:
int main() {HeapOnly* obj = HeapOnly::createInstance();// 使用对象obj->destroyInstance();return 0;
}
🚨🚨注意:在这种设计中,由于析构函数是私有的,不能直接使用delete
操作符来销毁对象。只能通过调用对象的destroyInstance()
函数来手动删除对象。
三、特殊类 — 只能在栈上创建对象的类
要设计一个只能在栈上创建对象的类,可以使用私有的构造函数和公有的静态成员函数来实现:
class StackOnly {
public:static StackOnly createInstance() {return StackOnly{};}private:StackOnly() = default; // 私有的默认构造函数,防止在堆上创建对象~StackOnly() = default; // 默认析构函数
};
这个类中,私有的构造函数阻止了在堆上创建对象。而通过公有的静态createInstance()
函数,可以在栈上创建该类的对象,并返回该对象的副本。由于没有指针和动态内存分配,对象的生命周期由对象所在的作用域控制,当对象离开作用域时,会自动调用析构函数销毁对象。
以下是示例代码的使用方式:
int main() {StackOnly obj = StackOnly::createInstance();// 使用对象return 0;
}
这样设计的类限制了对象只能在栈上创建,可以避免使用者误用动态内存分配,从而提高了代码的健壮性。但请注意,在这种设计中,对象的拷贝构造函数、赋值运算符重载函数需要适当处理,以确保对象的正确复制行为。
四、特殊类 — 不能被继承的类
1. C++98方式
// C++98中构造函数私有化,派生类中调不到基类的构造函数。则无法继承
class NonInherit
{
public:static NonInherit GetInstance(){return NonInherit();}
private:NonInherit(){}
};
🚨🚨注意:在C++98中,虽然可以将构造函数私有化以阻止派生类调用基类的构造函数,但这并不能完全阻止继承。派生类仍然可以继承基类的成员函数和非私有成员变量。
2. C++11方法
要设计一个不能被继承的类,可以使用C++中的关键字final
来实现:
class NonInheritable final {// 类的定义
};
通过在类的声明中添加final
关键字,可以阻止其他类继承该类。这样设计的类将是最终类,不能被其他类所继承。
以下是示例代码的使用方式:
class Derived : public NonInheritable { // 编译错误,无法继承NonInheritable类};int main() {NonInheritable obj; // 创建NonInheritable类的对象// 使用对象return 0;
}
这样设计的类不能被继承,可以确保类的封装性和稳定性,防止其他类对其进行修改或破坏。这在某些情况下非常有用,特别是当你希望限制类的继承性时。
总结
这些特殊类在面向对象编程中有着重要的作用,并且通过选择合适的类设计模式,我们可以更好地满足需求和解决问题。
在下一篇文章中,我们将深入研究单例模式。单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供了全局访问点。当我们需要确保只有一个对象来协调系统操作或管理共享资源时,单例模式非常有用。通过深入学习单例模式,我们将能够更好地理解其原理和使用方法,以及如何在实际开发中应用它。单例模式是一种非常有用的设计模式,掌握它将有助于我们编写可靠、高效的代码。让我们一起探索单例模式的精髓吧!敬请期待下一篇文章的发布!
温馨提示
感谢您对博主文章的关注与支持!另外,我计划在未来的更新中持续探讨与本文相关的内容,会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!
再次感谢您的支持和关注。期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
相关文章:

【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
阅读导航 引言一、特殊类 --- 不能被拷贝的类1. C98方式:2. C11方式: 二、特殊类 --- 只能在堆上创建对象的类三、特殊类 --- 只能在栈上创建对象的类四、特殊类 --- 不能被继承的类1. C98方式2. C11方法 总结温馨提示 引言 在面向对象编程中࿰…...

VMware虚拟机部署Linux Ubuntu系统
本文介绍基于VMware Workstation Pro虚拟机软件,配置Linux Ubuntu操作系统环境的方法。 首先,我们需要进行VMware Workstation Pro虚拟机软件的下载与安装。需要注意的是,VMware Workstation Pro软件是一个收费软件,而互联网中有很…...

RFID标签:数字时代的智能身份
在数字时代,RFID标签(Radio-Frequency Identification)成为物联网(IoT)中不可或缺的一环。作为一种小巧却功能强大的设备,RFID标签在各个领域的应用不断扩展,为我们的生活和工作带来了新的可能性…...

《动手学深度学习(PyTorch版)》笔记3.2
注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过。…...

elasticsearch8.x版本docker部署说明
前提,当前部署没有涉及证书和https访问 1、环境说明,我采用三个节点,每个节点启动两个es,用端口区分 主机角色ip和端口服务器Amaster192.168.2.223:9200服务器Adata192.168.2.223:9201服务器Bdata,master192.168.2.224:9200服务器Bdata192.1…...

使用scyllaDb 或者cassandra存储聊天记录
一、使用scyllaDb的原因 目前开源的聊天软件主要还是使用mysql存储数据,数据量大的时候比较麻烦; 我打算使用scyllaDB存储用户的聊天记录,主要考虑的优点是: 1)方便后期线性扩展服务器; 2)p…...

Visual Studio如何修改成英文版
1、打开 Visual Studio Installer 2、点击修改 3、找到语言包,选择需要的语言包,而后点击修改 4、等待下载 5、 安装完成后启动Visual Studio 6、在工具-->选项-->环境-->区域设置-->English并确定 7、重启 Visual Studio,配置…...

gin中使用swagger生成接口文档
想要使用gin-swagger为你的代码自动生成接口文档,一般需要下面三个步骤: 按照swagger要求给接口代码添加声明式注释,具体参照声明式注释格式。使用swag工具扫描代码自动生成API接口文档数据使用gin-swagger渲染在线接口文档页面 第一步&…...

最新AI创作系统ChatGPT网站系统源码,Midjourney绘画V6 ALPHA绘画模型,ChatFile文档对话总结+DALL-E3文生图
一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧。已支持GPT…...

解析dapp:从底层区块链看DApp的脆弱性和挑战
每天五分钟讲解一个互联网只是,大家好我是啊浩说模式Zeropan_HH 在Web3时代,去中心化应用程序(DApps)已成为数字经济的重要组成部分。它们的同生性,即与底层区块链网络紧密相连、共存亡的特性,为DApps带来…...

机器学习整理
绪论 什么是机器学习? 机器学习研究能够从经验中自动提升自身性能的计算机算法。 机器学习经历了哪几个阶段? 推理期:赋予机器逻辑推理能力 知识期:使机器拥有知识 学习期:让机器自己学习 什么是有监督学习和无监…...

RISC-V常用汇编指令
RISC-V寄存器表: RISC-V和常用的x86汇编语言存在许多的不同之处,下面将列出其中部分指令作用: 指令语法描述addiaddi rd,rs1,imm将寄存器rs1的值与立即数imm相加并存入寄存器rdldld t0, 0(t1)将t1的值加上0,将这个值作为地址,取…...

第二篇:数据结构与算法-链表
概念 链表是线性表的链式存储方式,逻辑上相邻的数据在计算机内的存储位置不必须相邻, 可以给每个元素附加一个指针域,指向下一个元素的存储位 置。 每个结点包含两个域:数据域和指针域,指针域存储下一个结点的地址&…...

低代码配置-小程序配置
数据结构 {"data": {"layout": {"api":{"pageApi":{//api详情}},"config":{"title":"页面标题",},"listLayout": {"fields": [{"componentCode": "grid…...

第十八讲_HarmonyOS应用开发实战(实现电商首页)
HarmonyOS应用开发实战(实现电商首页) 1. 项目涉及知识点罗列2. 项目目录结构介绍3. 最终的效果图4. 部分源码展示 1. 项目涉及知识点罗列 掌握HUAWEI DevEco Studio开发工具掌握创建HarmonyOS应用工程掌握ArkUI自定义组件掌握Entry、Component、Builde…...

OJAC近屿智能张立赛博士揭秘GPT Store:技术创新、商业模式与未来趋势
Look!👀我们的大模型商业化落地产品📖更多AI资讯请👉🏾关注Free三天集训营助教在线为您火热答疑👩🏼🏫 亲爱的伙伴们: 1月31日晚上8:30,由哈尔滨工业大学的…...

Java接收curl发出的中文请求无法解析
最近做项目遇到了这种情况,Java接收curl发出的中文请求无法解析,英文请求一切正常,中文请求则对方服务器无法解析,可以猜测是中文导致的编码问题,但是奇怪的是,本地输出json也没有乱码,编解码正…...

Java设计模式-外观模式(11)
大家好,我是馆长!今天开始我们讲的是结构型模式中的外观模式。老规矩,讲解之前再次熟悉下结构型模式包含:代理模式、适配器模式、桥接模式、装饰器模式、外观模式、享元模式、组合模式,共7种设计模式。。 外观模式(Decorator Pattern) 定义 外观(Facade)模式一种通…...

HCS-华为云Stack-FusionSphere
HCS-华为云Stack-FusionSphere FusionSphere是华为面向多行业客户推出的云操作系统解决方案。 FusionSphere基于开放的OpenStack架构,并针对企业云计算数据中心场景进行设计和优化,提供了强大的虚拟化功能和资源池管理能力、丰富的云基础服务组件和工具…...

C++类模板实现顺序表SeqList
main函数 #include<iostream> #include<stdlib.h> #include"SeqList.cpp"using namespace std;typedef int ElementType; int main(void) {SeqList< ElementType, 10> SeqList(1);cout << SeqList.ListLength() << endl;bool result;…...

sklearn 学习-混淆矩阵 Confusion matrix
混淆矩阵Confusion matrix:也称为误差矩阵,通过计算得出矩阵的结果用来表示分类器的精度。其每一列代表预测值,每一行代表的是实际的类别。 from sklearn.metrics import confusion_matrixy_true [2, 0, 2, 2, 0, 1] y_pred [0, 0, 2, 2, 0…...

C#,数据检索算法之跳跃搜索(Jump Search)的源代码
数据检索算法是指从数据集合(数组、表、哈希表等)中检索指定的数据项。 数据检索算法是所有算法的基础算法之一。 本文提供跳跃搜索的源代码。 1 文本格式 using System; namespace Legalsoft.Truffer.Algorithm { public static class ArraySe…...

ElasticSearch 开发总结(九)——SearchType:DFS_QUERY_THEN_FETCH和QUERY_THEN_FETCH
ElasticSearch 开发总结(九)——SearchType:DFS_QUERY_THEN_FETCH和QUERY_THEN_FETCH-CSDN博客 1.SearchType ES的搜索类型 有一个类SearchType(如下图示),关于该类的描述: Search type repre…...

那些年与指针的爱恨情仇(一)---- 指针本质及其相关性质用法
关注小庄 顿顿解馋 (≧∇≦) 引言: 小伙伴们在学习c语言过程中是否因为指针而困扰,指针简直就像是小说女主,它逃咱追,我们插翅难飞…本篇文章让博主为你打理打理指针这个傲娇鬼吧~ 本节我们将认识到指针本质,何为指针和…...

计算机网络——TCP协议
💡TCP的可靠不在于它是否可以把数据100%传输过去,而是 1.发送方发去数据后,可以知道接收方是否收到数据;2.如果接收方没收到,可以有补救手段; 图1.TCP组成图 TCP的可靠性是付出代价的,即传输效率…...

软考高级有意义吗?
有同学在平台向我提问,软考高级好像不好通过,花那么多时间去准备(非科班),有意义么? 我知道有些同学还在犹豫,不确定是否要报名软考系统架构设计师或者系统分析师。我认为,这种犹豫…...

二分算法模版
二分算法模版 实数二分算法模版实数二分模版题 整数二分算法模版向上取整二分模版向下取整二分模版二分模版的注意点二分模版中check函数的实现能够使用二分的条件 二分主要分两类, 一类是对实数进行二分,一类是对整数进行二分 对整数二分又分成2种&…...

【CSS】字体效果展示
测试时使用了Google浏览器。 1.Courier New 2.monospace 3.Franklin Gothic Medium 4.Arial Narrow 5.Arial 6.sans-serif 7.Gill Sans MT 8.Calibri 9.Trebuchet MS 10.Lucida Sans 11.Lucida Grande 12.Lucida Sans Unicode 13.Geneva 14.Verdana 15.Segoe UI 16.Tahoma 17.…...

asp.net宠物流浪救助系统
asp.net宠物流浪救助系统 当领养人是无或者未领养的时候,就会显示领养申请按钮,登陆的用户可以申请领域该宠物,未登录会提示登陆然后转到登陆页面 宠物领养页面支持关键字查询符合条件的宠物 当有领养人时就隐藏领养申请按钮 社区交流意见…...

git常见命令
1、常用命令记录 1)切换分支 git checkout 分支名2)查看分支 查看远程分支 git branch -r 查看所有分支包括本地分支和远程分支 git branch -a3)合并分支 git merge 来源分支4)删除分支 删除本地分支:git branch …...