news 2026/7/22 8:14:37

C++:特殊类设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++:特殊类设计

目录

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

2. 只能在堆上创建对象,不能在栈上或全局/静态区直接创建对象

2.1 方案1

2.2 方案二

3.只能在栈上创建对象

4.不能被继承


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

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

C++98 可将拷贝构造函数与赋值运算符重载只声明不定义,并且将其访问权限设置为私有即可。

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

原因:

  1. 设置成私有:如果只声明没有设置成private,用户自己如果在类外定义了,就可以不能禁止拷贝了
  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不会防止成员函数内部拷贝了。

C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。

class CopyBan { // ... CopyBan(const CopyBan&)=delete; CopyBan& operator=(const CopyBan&)=delete; //... };

2. 只能在堆上创建对象,不能在栈上或全局/静态区直接创建对象

只能在堆上创建对象,说明只能通过只指针的方式指向对象,在构造和析构函数上做文章。

2.1 方案1

析构函数私有化,然后需要提供 delete 的方法,有两种delete方式。

class HeapOnly { public: //不加static也行,必须实例化,p1->Destory1,p1不能为空 //加上static可以实例化调用,C++ 保证 delete nullptr 无操作 static void Destroy1(HeapOnly* ptr) { //合法:因为这是在 HeapOnly 的成员函数内部, //可以访问 HeapOnly 的私有成员函数和数据成员,调用 delete 来销毁对象。 delete ptr; } void Destroy2() { delete this; } private: ~HeapOnly() { cout << "~HeapOnly" << endl; } };

这样就不能直接创建对象了,因为这样必须需要构造函数,new 操作只负责“构造”,不负责“析构”。然后可以通过下面三种方式释放空间(只能使用一个)。类内的 this 就是 ptr ,就是指向类的指针但静态成员函数中不能直接用 this 和 析构,因为 this 是一个具体的对象。

int main() { //HeapOnly hp1; //static HeapOnly hp2;//执行完都需要 自动 调用析构函数, 会出问题,不能在栈上或全局/静态区 直接创建对象 HeapOnly* hp3 = new HeapOnly; //执行delete 自定义类型,会调用析构函数,失败 //delete hp3;//不能直接释放,因为也要调用析构函数 //也不用再主动 delete 释放了,可以调用内部函数完成。 HeapOnly::Destroy1(hp3);//1. 通过静态成员函数来销毁对象,成功 hp3->Destroy1(hp3);//2. 通过对象来调用静态成员函数来销毁对象,成功 hp3->Destroy2();//3. 通过this指针来销毁对象,成功 return 0; }

2.2 方案二

构造函数私有化,那就提供一个 static 构造的方法

这里必须加static,因为调用成员函数需要现有对象,而对象只能通过构造函数,但构造函数私有化了,先有鸡还是先有蛋问题。拷贝构造 和 operator= 也应该禁掉。

class HeapOnly { public: //不加static不行,因为调用成员函数需要现有对象, //而对象只能通过构造函数,但构造函数私有化了 static HeapOnly* CreateObj() { return new HeapOnly; //合法:因为这是在 HeapOnly 的成员函数内部, //可以访问 HeapOnly 的私有成员函数和数据成员,调用 new 来创建对象。 } // 禁止拷贝和移动构造(防止栈上通过已有对象创建新对象) HeapOnly(const HeapOnly&) = delete; HeapOnly(HeapOnly&&) = delete;//move()后可以调用 // 禁止拷贝和移动赋值(虽不创建新对象,但为逻辑完整) HeapOnly& operator=(const HeapOnly&) = delete; HeapOnly& operator=(HeapOnly&&) = delete; private: HeapOnly()//构造函数私有化,不能在栈上或全局/静态区 直接创建对象 { } }; int main() { HeapOnly* hp1 = HeapOnly::CreateObj(); //合法:静态函数才能成功 return 0; }

3.只能在栈上创建对象

无法 new,所以必须构造函数私有,然后提供一个 static 的函数来构造。这里是无参的,当然也可以传递参数。拷贝构造函数不能禁掉,因为要传值返回,传不了指针,因为函数内部创建的是局部变量,如果是创建一个 static 对象,那么全局就只有一个 StaticOnly 指针了,也不行。

class StackOnly { public: static StackOnly CreateObj() { return StackOnly(); } //StackOnly(const StackOnly& st) = delete;//禁掉后无法 CreateObj 传值返回 void* operator new(size_t size) = delete;//相当于间接禁用new。或者设为私有 //当然我们也可以operator 重载new //void* operator new(size_t size) //{ // cout << "void * operator new(size_t size)" << endl; // return malloc(size); //} private: StackOnly() {} // 构造函数私有化,禁止在堆上创建对象 }; int main() { //因为new必须调用构造函数来创建对象,所以当构造函数私有化时,无法在堆上创建对象,只能在栈上创建对象。 StackOnly obj1 = StackOnly::CreateObj(); // 合法:通过静态成员函数创建对象 return 0; }

new StackOnly(obj1) 执行两步

  1. 调用 operator new 分配堆内存。operator new是全局的,当然这里重载自己的专属operator new,不调用全局的。
  2. 在分配的内存上调用拷贝构造函数,用 obj1 作为参数初始化这个新对象。因为拷贝构造函数是 public,所以这一步合法。而不使用()直接new 调用的才是构造函数,
StackOnly* obj2 = new StackOnly(obj1);

4.不能被继承

C++98方式:

因为子类构造要调用父类的构造,同上将构造函数私有化,然后设计静态方法创建对象返回即可。

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

C++11方法:final关键字,final修饰类,表示该类不能被继承。

class A final { // .... };

本篇结束!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 8:14:32

Claude Code与MCP工具链整合开发指南

1. Claude Code与MCP工具链的深度整合在探索Claude Code与MCP工具链的整合之前&#xff0c;我们需要先理解这两个核心组件各自的功能定位。Claude Code作为新一代智能编程助手&#xff0c;其核心价值在于将自然语言指令转化为可执行代码逻辑。而MCP&#xff08;Microservice Co…

作者头像 李华
网站建设 2026/7/22 8:12:25

墨香情新手入门指南:从门派选择到高效升级

1. 墨香情新手入门&#xff1a;游戏背景与核心玩法解析 墨香情作为一款融合了东方武侠元素与社交玩法的MMORPG&#xff0c;自上线以来就凭借其独特的画风和丰富的系统吸引了大量玩家。对于刚接触这款游戏的新手而言&#xff0c;理解游戏的基本架构是顺利开荒的第一步。 游戏世…

作者头像 李华
网站建设 2026/7/22 8:12:17

C++ Boost库全面解析:从核心组件到网络编程实战

1. 项目概述&#xff1a;为什么C开发者绕不开Boost&#xff1f; 如果你用C写过几年项目&#xff0c;尤其是在处理网络通信、字符串解析、数据结构或者需要跨平台部署的时候&#xff0c;大概率会听到过“Boost”这个名字。它不是某个新潮的框架&#xff0c;而是一个庞大、成熟且…

作者头像 李华
网站建设 2026/7/22 8:10:02

C++游戏AI实战:行为树与状态机融合架构设计与性能优化

1. 项目概述&#xff1a;从“呆板”到“灵动”的AI进化之路 如果你也曾在游戏开发中&#xff0c;面对那些只会沿着固定路线巡逻、发现玩家后只会直线冲锋、或者在不同行为间切换时显得生硬卡顿的NPC&#xff08;非玩家角色&#xff09;而感到头疼&#xff0c;那么你遇到的核心问…

作者头像 李华
网站建设 2026/7/22 8:09:36

AI+iPaaS自动化工作流:企业数字化转型的核心引擎

1. AIiPaaS自动化工作流的核心价值 在数字化转型浪潮中&#xff0c;企业普遍面临系统孤岛、数据割裂和重复劳动三大痛点。我去年为某零售客户实施自动化方案时&#xff0c;他们每天需要人工从15个不同系统导出数据并手工制作报表&#xff0c;仅这项操作就消耗3个员工全天工作量…

作者头像 李华