C++ 常见特殊类的设计

 一、设计一个不能被拷贝的类

1.1 为什么需要一些不能被拷贝的类呢?

很多情况下如果允许进行拷贝逻辑是说不通的,比如IO流有缓冲区如何进行拷贝,又比如说对于线程这个类,线程对象已经运行了如何进行拷贝?

想要让某个类不能被拷贝直接将拷贝构造函数和operator=封死就可以解决了。

1.2 策略

C++98中的做法是:

将构造函数私有化并只声明不定义

class CopyBan { public: //... private: CopyBan(const CopyBan& cb); CopyBan& operator=(const CopyBan& cb); //... };

这种私有化+只声明不定义的策略是因为:

现来说一下私有化,私有化防止进行该类实例化出来的对象执行拷贝和复制重载;只声明不定义是因为该函数不可能被调用,将这两个函数进行定义也没有任何意义,如果不声明的话会自动在publish中生成默认构造函数就会允许拷贝构造和赋值重载了。

C++11中的做法是:

通过在函数后面加上 delete关键字(准确的说是加上 = delete)

class CopyBan { public: CopyBan(const CopyBan& cb) = delete; CopyBan operator=(const CopyBan& cb) = delete; private: //... };

通过使用 = delete 让编译器进行删除该类的构造函数。

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

2.1 策略

构造函数私有化

要想让一个类只能在堆上进行创建空间,也就是说需要将传统的通过构造函数进行在栈上进行创建对象的这种方式进行封锁,然后进行提供提供一个静态的公共函数接口,专门用来提供在对上进行创建对象的这种需求。

class HeapOnly { public: static HeapOnly* CreateObject() { return new HeapOnly; } private: HeapOnly() { } HeapOnly(const HeapOnly& ho) = delete; HeapOnly& operator=(const HeapOnly& ho) = delete; };
这里说明一下为什么也要将拷贝构造和赋值重载进行封死?



如果要不封死,虽然不能通过构造函数进行在栈上进行创建对象,但是可以先通过在堆上进行创建对象再通过拷贝构造或者赋值重载在栈上进行创建。

还有一种非常特别的思路

将析构函数进行私有化

class HeapOnly { public: HeapOnly() { } void DeleteObject() { delete this; } private: HeapOnly(const HeapOnly& ho) = delete; HeapOnly& operator=(const HeapOnly& ho) = delete; ~HeapOnly() { } };

将析构函数进行私有化这种策略是利用了编译器的性质,当编译器识别到在栈上进行创建对象时,会考虑到该对象的作用域,超过作用域会将该对象进行销毁并进行资源释放,当将析构函数进行私有化时,此时编译器在进行识别到在栈上进行创建对象时,发现析构函数定义在了private中意味着不能进行在类外调用,此时就会报错,不允许在堆上进行创建对象。

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

3.1 策略

先说一种错误的策略:

构造函数私有化


想要将一个设计成只能在栈上进行创建对象,首先肯定要禁止 new 进行创建对象,new 关键字进行创建对象本质上又在类外调用了构造函数,所以将类的构造函数进行私有化即可屏蔽在类外进行通过new进行创建对象,但是还要在栈上能创建对象,所以还需要在类中的public中进行定义一个创建对象的静态成员函数。

这样进行实验是确实可以通过编译的,但是这样进行构建的对象是死的,无法将 CreateObject 函数进行创建出来的对象进行赋值给外面进行接收的对象,这些都是在c++17之前;但是c++17之后是允许通过编译的,之所以能够通过编译是因为这个return StackOnly()这行代码在c++17之前是先进行创建临时对象将临时对象拷贝或者移动到外面接收的变量中,但是c++17之后直接将拿着这个对象中的成员一个一个赋值给外面对象的成员,既然没有临时对象也就不在涉及拷贝构造。

这里能编译通过也是很坑的,举个例子:
 

vector容器中存储的元素是在堆上,当通过vec对象进行调用push_back想要将s对象进行存储到容器中时,此时会报错,因为:push_back并不会直接收纳s本身,是在栈上容器存储的是在堆上,真正的逻辑是:

在堆上找到一个空位

然后调用s的拷贝构造函数将s中的数据进行拷贝到堆上

正确的方式

将 new 和 delete 系类的函数禁用

class StackOnly { public: StackOnly() { } ~StackOnly() { } static void* operator new(size_t sz) = delete; static void operator delete(void* memy) = delete; static void* operator new[](size_t sz) = delete; static void operator delete[](void* memy) = delete; };

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

4.1 策略

c++98 做法:将构造函数私有化

将基类的构造函数私有化,当子类进行继承基类时并且进行定义对象时,此时该对象会进行调用基类和子类的构造函数进行初始化,但是基类中构造函数私有了,调不到从而做到基类无法被继承。

class NonInherit { public: static NonInherit GetInstance() { return NonInherit(); } private: NonInherit() {} };

c++11 做法:利用 final 关键字进行修饰

class NonInherit final { // .... };

Read more

Java常见面试题及答案汇总(2025最新版)

一、Java基础语法与核心特性 1. Java的核心特性有哪些? 答案: * 跨平台性(Write Once, Run Anywhere):通过JVM(Java虚拟机)实现,字节码文件可在任意支持JVM的操作系统运行; * 面向对象(OOP):封装、继承、多态三大核心特性; * 安全性:支持沙箱机制、字节码校验、权限控制(如文件IO权限); * 健壮性:自动垃圾回收(GC)避免内存泄漏,强类型检查、异常处理机制减少运行时错误; * 分布式:支持RMI(远程方法调用)、HTTP协议,便于开发分布式应用; * 多线程:内置多线程API,支持并发编程。 2. 基本数据类型与包装类的区别? 答案: 维度基本数据类型(如int、float)包装类(如Integer、Float)本质原始值,无对象属性引用类型,继承Object类默认值有(

By Ne0inhk
Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射

Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 js_wrapping 的鸿蒙化适配指南 - 实现 Dart 与 JavaScript 的无缝对象包装、支持强类型回调与属性映射 前言 在进行 Flutter for OpenHarmony 的 Web 混合开发时,频繁地在 Dart 层与底层 JavaScript 环境进行数据交互是不可避免的。虽然官方提供了基本的 dart:js,但在处理复杂的 JS 对象和回调时,代码往往会变得杂乱无章。js_wrapping 提供了一个更优雅的、类型安全的包装层。本文将指导大家如何在鸿蒙端利用该库提升 JS 互操作的开发体验。 一、原理解析 / 概念介绍 1.1 基础原理

By Ne0inhk

[AI提效-20]-豆包实操指南:高效完成学术论文的搜索与解读(新手也能上手)

学术研究、论文写作中,我们常陷入两大困境:一是找不到精准匹配的权威论文,翻遍知网、万方却被无关文献淹没,浪费大量时间;二是读懂论文难,尤其是英文文献、专业度高的实证论文,面对复杂的研究方法、晦涩的理论表述,半天抓不住核心要点,更无法高效复用其中的研究思路和成果。 其实,借助豆包的AI能力(学术搜索、多模态解读、逻辑梳理、翻译辅助等),就能轻松解决这两大痛点——不用手动筛选文献、不用逐字啃晦涩表述,新手也能在1-2小时内,完成“精准搜论文→快速读论文→吃透核心要点”的全流程,适配本科、硕士论文写作、课题研究等各类学术场景。 本文将手把手教你,如何使用豆包进行学术论文的搜索与解读,从搜索入口定位、精准指令搭建,到论文拆解、要点提炼,每一步都附具体操作和指令模板,直接套用就能提升学术效率,避免无效内耗。 一、先搞懂核心:豆包在学术论文场景的核心优势 很多人只用豆包聊天、问基础问题,却忽略了它的学术赋能能力——相较于传统文献检索工具(知网、万方)

By Ne0inhk