前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++】特殊类设计 — 不能被拷贝的类 , 只能在堆/栈上创建对象的类 ,不能被继承的类

【C++】特殊类设计 — 不能被拷贝的类 , 只能在堆/栈上创建对象的类 ,不能被继承的类

作者头像
叫我龙翔
发布2024-08-15 14:31:40
880
发布2024-08-15 14:31:40
举报
文章被收录于专栏:就业 C++ 综合学习

1 特殊类

在实践中,常常会有一些比较有意思的特殊场景:

  1. 不能被拷贝的类 - 独一无二的魔法宝物: 在一个角色扮演游戏(RPG)。在这个游戏中,玩家可以通过工匠进行装备的拷贝,但是有一件神秘的魔法宝物,被称为“永恒之心”,它拥有赋予持有者永生的力量 ,是独一无二的,因此它不能被复制或克隆。 每当玩家尝试复制“永恒之心”时,游戏会抛出一个错误:“魔法宝物独一无二,无法复制!”。这确保了游戏中只有一个“永恒之心”,增加了它的神秘感和价值。
  2. 只能在堆上创建对象的类 - 豪华游艇 有一个豪华游艇模拟器。在这个模拟器中,游艇是一个复杂且昂贵的对象,它需要在堆上动态分配资源,比如内存来存储游艇的详细规格和状态。 每当玩家想要创建一艘新的游艇时,他们必须通过“造船厂”接口来请求,这实际上是在堆上分配了一个新的游艇对象。
  3. 只能在栈上创建对象的类 - 一次性密码 你正在为银行的安全系统编写代码。为了防止密码被复制或存储在不可靠的地方,你设计了一个“一次性密码”类,它只能在栈上创建,并在使用后立即销毁。 当用户进行一次交易时,系统会生成一个一次性密码,一旦交易完成,密码就会“消失”,保证了密码的安全性。 … 在这些特殊场景中,我们需要按照需求设计是特殊类!

2 不能被拷贝的类

拷贝只会发生在两个场景中:拷贝构造函数以及赋值运算符重载 因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可 在C++98中我们会将拷贝构造函数和赋值重载函数进行私有化,这样外部就调用不到他们了!

代码语言:javascript
复制
class A
{
	A()
	{}
	~A()
	{}
private:
	A(const A& a)
	{
	}
	A& operator=(const A& a)
	{
	}
private:
	int _a1;
};
  1. 必须设置成私有:如果只声明没有设置成private,如果在类外定义拷贝构造和赋值重载,就不能禁止拷贝了!
  2. 只声明不定义:不定义是因为该函数根本不会调用,定义了其实也没有什么意义,不写反而还简单,而且如果定义了就不能防止成员函数内部拷贝了!

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

代码语言:javascript
复制
class A
{
	A()
	{}
	~A()
	{}

	A(const A& a) = delete;
	A& operator=(const A& a) = delete;

private:
	int _a1;
};

这样就轻松的解决了问题!

3 只能在堆上创建对象的类

使用使用的类,就不能让用户,可以显式调用到构造函数,不然就在栈区创建了对象!我们需要写出一个接口,让用户可以获取到堆上的对象地址!这样就涉及到了先有鸡先有蛋的问题了,所以我们要将这个接口设置成静态成员函数,才能正常调用!

代码语言:javascript
复制
class HeapOnly
{
public:
	static HeapOnly* CreateObj()
	{
		return new HeapOnly;
	}
private:
	HeapOnly()
	{
	}
	HeapOnly(const HeapOnly& h) = delete;
	HeapOnly& operator=(const HeapOnly& a) = delete;
private:
	int _a1;
};

注意:除了处理构造函数,还要处理拷贝构造和赋值拷贝函数。因为拷贝的对象也是在栈上的!必须把所有可能的方法都要封死!

这样一个只能在堆上创建对象的类就写好了!

还有一个十分新奇的写法:将析构函数私有化!这样在栈上创建对象就会报错,迫使用户只能在堆上构造对象!我们可以通过一个显式的release方法来释放空间,来完善在堆上创建对象的操作!

4 只能在栈上创建对象的类

同上将构造函数私有化,然后设计静态方法创建对象返回.注意为了防止在堆上创建对象,我们需要将new delete操作符重载函数进行删除!这样就将在堆上创建彻底封死了!

代码语言:javascript
复制
class StackOnly
{
public:
	static StackOnly CreateObj()
	{
		return StackOnly();
	}
	// 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉
	// StackOnly obj = StackOnly::CreateObj();
	// StackOnly* ptr3 = new StackOnly(obj);
	void* operator new(size_t size) = delete;
	void operator delete(void* p) = delete;
private:
	StackOnly()
		:_a(0)
	{}
private:
	int _a;
};

5 不能被继承的类

回顾一下继承的知识:从零开始认识继承

不能被继承的类很简单!C++98是将构造函数进行私有化,在C++11之后直接使用final关键字就可以了!

代码语言:javascript
复制
class A final
{
	// ....
};

总结

C++的世界里,一些特别的类真是挺有讲究的。就像游戏里的独门魔法宝物,模拟豪华游艇的细节,还有银行系统里那些用完就丢的密码,每一个都是针对特定情况精心设计的。那些不能复制的类,就像是在说“我是特别的,不能随便复制”;只能在堆上或者栈上创建对象的类,就像是给内存管理上了把锁,保证了东西放在该放的地方;而不让继承的类,就像是定了规矩,让功能保持原汁原味。

这些设计不仅展示了C++的强大,也让我们看到程序员先辈们是如何巧妙地解决难题的。通过这几个特殊的类,我们的代码能力肯定有许多长进,C++的学习过程也变得更加丰富多彩了!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 特殊类
  • 2 不能被拷贝的类
  • 3 只能在堆上创建对象的类
  • 4 只能在栈上创建对象的类
  • 5 不能被继承的类
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档