特殊设计模式

实现一个类,不能被拷贝

实现一个类,只能在堆上创建

实现一个类,只能创建在栈上

设计一个不能继承的类

单例模式------一个类只能生成一个对象

饿汉模式------在每次程序启动都会自动生成一个对象

懒汉模式------在第一次需要的时候创建

🔱实现一个类,不能被拷贝

拷贝可能需要调用拷贝构造,operator=

cpp 复制代码
class CopyBan
{
public:
	// c++11
	CopyBan() = default;
	CopyBan(const CopyBan&) = delete;
	CopyBan& operator=(const CopyBan&) = delete;
private:
	// c98
	// CopyBan(const CopyBan&);
	// CopyBan& operator=(const CopyBan&) ;
};

第一种采用c++11delete关键字

第二种采用c++98声明成私有的方式实现


🔱实现一个类,只能在堆上创建

因为new HeapOnly() 需要调用默认构造函数,所以不能将默认构造函数禁掉,需要将默认构造函数管理起来
new HeapOnly(...) 可能调用有参构造,拷贝构造

cpp 复制代码
// 设计一个只能创建在堆上的类
class HeapOnly
{
public:
	static HeapOnly* CreateObject(); 
private:
	// 因为new HeapOnly() 需要调用默认构造函数,所以不能将默认构造函数禁掉,需要将默认构造函数管理起来
	// new HeapOnly(...) 可能调用有参构造,拷贝构造
	// 
	HeapOnly()
	{
		cout << "HeapOnly()" << endl;
	}
	// HeapOnly* b = new HeapOnly;
	// HeapOnly a(b); 这种是创建在栈上
	// 所以为了严格管理创建在堆上,需要不能写HeapOnly(const HeapOnly*);
	HeapOnly(const HeapOnly&) = delete;
	HeapOnly& operator=(const HeapOnly&) = delete;
};
HeapOnly* HeapOnly::CreateObject()
{
	return new HeapOnly();
}
  1. 堆上创建对象,都是需要通过new进行创建
  2. 可能会想返回值是new的对象能不能表示创建在堆上???
    答案是不能;返回值是堆上的对象,只能说返回的是堆上的对象,但是你自己的这个对象还是栈上开辟的

🔱实现一个类,只能创建在栈上

无参构造是需要的------需要在栈上创建

但是不能在堆上创建,所以不能使用new StackOnly,这个会调用默认构造函数,所以要将默认构造函数管理起来

只需要将new禁掉就行了,还有delete

cpp 复制代码
// 设计一个只能创建在栈上的类
class StackOnly
{
public:
	void* operator new(size_t size) = delete;
	void operator delete(void* p) = delete;
private:
	// 无参构造是需要的------需要在栈上创建
	// 但是不能在对上创建,所以不能使用new StackOnly,这个会调用默认构造函数,所以要将默认构造函数管理起来

	// 只需要将new禁掉就行了,还有delete
};

🔱设计一个不能继承的类

需要明确继承是需要默认调用父类的构造函数------默认构造,有参构造,拷贝构造,operator=

所以需要将这写函数管理起来,首先不能将这些函数禁掉,所以就需要手动管理起来

c++98的方式

默认构造,有参构造,拷贝构造,operator= 写成private

cpp 复制代码
class NonInherit
{
public:
	// 需要明确继承是需要默认父类的构造函数------默认构造,有参构造,拷贝构造,operator=
	// 所以需要将这写函数管理起来,首先不能将这些函数禁掉,所以就需要手动管理起来
	// c++11 的方式 final这个方法更好,支持在堆上创建,而且使用final编译器会有报错
	// c++98 的方式 private
private:
	// 如果使用c++98的方式,这个类就不能在堆上创建对象了,所以不太好,需要换种方式
	NonInherit();
	NonInherit(const NonInherit&);
	NonInherit& operator=(const NonInherit&);
};

如果使用private方式,这个类就不能在堆上创建对象,所以不太好,需要换种方式

我们额外在多想一下,为什么不能将父类构造函数分别放到protect,private中,子类使用protect,private继承

  1. 对于public,protect 属性取与继承方式范围小的那个
    比如说,protect属性+private继承方式=子类中private可见------父类protect属性成员转变成子类的private成员;public属性也是类似
  2. 对于private属性使用任何继承方式在子类中都是不可见的------就像爸爸的私有物品,儿子使用什么方式都是看不到的

这也是为什么不将父类构造函数写成protect的原因,所以将父类构造函数写成private属性很安全

不懂的可以看一下这个文章------各种继承方式在子类中的可见性


c++11的方式

定义父类名使用final

cpp 复制代码
class NonInherit final
{
public:
	// 需要明确继承是需要默认父类的构造函数------默认构造,有参构造,拷贝构造,operator=
	// 所以需要将这写函数管理起来,首先不能将这些函数禁掉,所以就需要手动管理起来
	// c++11 的方式 final这个方法更好,支持在堆上创建,而且使用final编译器会有报错
	// c++98 的方式 private
private:
	// 如果使用c++98的方式,这个类就不能在堆上创建对象了,所以不太好,需要换种方式
	//NonInherit();
	//NonInherit(const NonInherit&);
	//NonInherit& operator=(const NonInherit&);
};

c++11 的方式 final这个方法更好,支持在堆上创建,而且使用final编译器会有报错


🔱单例模式------一个类只能生成一个对象

✨饿汉模式------在每次程序启动都会自动生成一个对象

比如在某个服务器程序中,该服务器的配置

信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再

通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

cpp 复制代码
// 饿汉模式
class Singleton_hunger
{
	// 在程序运行起来就已经准备好了对象,并且这个对象只能有一个
public:

	Singleton_hunger(const Singleton_hunger&) = delete;
	Singleton_hunger& operator=(const Singleton_hunger&) = delete;
	// 这个函数必须是static,如果普通函数,就需要先有对象才能访问函数,但是不能创建对象------必须是static
	static Singleton_hunger* GetSingleton_hunger()
	{
		return &tem;
	}
private:
	Singleton_hunger()
	{
		cout << "Singleton_hunger" << endl;
	}
	// 静态成员也受访问区域限制
	static Singleton_hunger tem;
};
Singleton_hunger Singleton_hunger::tem;

静态成员可以调用构造函数


✨懒汉模式------在第一次需要的时候创建

如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取

文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,

就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式(延迟加载)更好。

cpp 复制代码
// 懒汉模式
class Singleton_lazy
{
	// 懒汉模式------在需要的时候创建,并且符合单例模式
public:
	Singleton_lazy(const Singleton_lazy&) = delete;
	Singleton_lazy& operator=(const Singleton_lazy&) = delete;
	// 这个函数必须是static,如果普通函数,就需要先有对象才能访问函数,但是不能创建对象------必须是static
	static Singleton_lazy* GetSingleton_lazy()
	{
		if (tem == nullptr)
			tem = new Singleton_lazy;
		return tem;
	}
private:
	Singleton_lazy()
	{
		cout << "Singleton_lazy" << endl;
	}
	static Singleton_lazy* tem;
};
Singleton_lazy* Singleton_lazy::tem = nullptr;

在懒汉模式中需要需要使用指针来记录对象

  1. 可以使用nullptr表示没有初始化,一举两得,可以省去用另一个变量标记是否初始化
  2. 另一个原因
cpp 复制代码
	static Singleton_lazy GetSingleton_lazy()
	{
		if (_flag == 0)
		    tem = Singleton_lazy();
		return tem;
	}


单例模式并未结束,后来会添加线程知识

本次学习到此就结束了,只是讲了最基本的设计模式,还有很多设计模式需要我们去学习,加油!!!

相关推荐
CHANG_THE_WORLD几秒前
C++并发编程指南04
开发语言·c++
轩情吖12 分钟前
二叉树-堆(补充)
c语言·数据结构·c++·后端·二叉树··排序
iqay5 小时前
【C语言】填空题/程序填空题1
c语言·开发语言·数据结构·c++·算法·c#
程序猿编码5 小时前
自定义命令执行器:C++中命令封装的深度探索(C/C++实现)
linux·c语言·c++·网络安全·shell·命令行
wen__xvn6 小时前
每日一题洛谷B3865 [GESP202309 二级] 小杨的 X 字矩阵c++
c++·算法·矩阵
makabaka_T_T6 小时前
25寒假算法刷题 | Day1 | LeetCode 240. 搜索二维矩阵 II,148. 排序链表
数据结构·c++·算法·leetcode·链表·矩阵
学游戏开发的7 小时前
UE求职Demo开发日志#19 给物品找图标,实现装备增加属性,背包栏UI显示装备
c++·笔记·游戏引擎·unreal engine
c-c-developer8 小时前
C++ Primer 标准库类型string
开发语言·c++
宁静致远20218 小时前
Ubuntu下的Doxygen+VScode实现C/C++接口文档自动生成
c++·vscode·ubuntu
Bluesonli8 小时前
第 2 天:创建你的第一个 UE5 C++ 项目!
c++·学习·ue5·虚幻·虚幻引擎·unreal engine