特殊类的设计

不能背拷贝的类

不能调用拷贝构造和赋值运算符重载

c++98实现方式:

cpp 复制代码
class myClass {
public:
	myClass() {
		//
	}
private:
	myClass(const myClass&);
	myClass& operator=(const myClass&);
};

定义为私有是为了在外面不能被调用,只声明不是实现是为了内部不会调用,友元类不能调用,书写反而简单

补充:如果函数只是声明或者在函数内部没有使用形参,可以不写形参名

c++11实现方式:

cpp 复制代码
class myClass {
public:
	myClass() {
		//
	}
	myClass(const myClass&)=delete;
	myClass& operator=(const myClass&)=delete;
private:
};

默认成员函数=delete;表示直接删除这个默认成员函数

只能在堆上创建对象的类

只能通过new,malloc等申请的对象

实现方式:

1.私有构造函数,防止外部通过构造函数创建对象,删除拷贝构造和赋值运算符重载

2.提供一个静态函数,在函数内部实现从堆上创建对象

cpp 复制代码
class myClass {
public:
	static myClass* createObject() {
		return new myClass;
	}
	myClass(const myClass&)=delete;
	myClass& operator=(const myClass&)=delete;
private:
	myClass() {
		//
	}
};

只能在栈上创建对象的类

不能通过new,malloc等申请资源

实现方式:

1.私有构造函数,提供一个静态函数,创建对象并返回

2.内部重载new 并删除

cpp 复制代码
class myClass {
public:
	static myClass createObject() {
		return myClass();
	}
	void* operator new(size_t size) = delete;
private:
	myClass() {
		//
	}
};

补充:当new一个对象时,是不是先看类域中有没有重载new,如果没有,从全局中寻找new

设计一个类不能被继承

c++98方式:

cpp 复制代码
class myClass {
public:
	static myClass createObject() {
		return myClass();
	}
private:
	myClass() {
		//
	}
};

如果有个派生类继承myClass,当创建对象时,需要调用基类的构造函数,但myClass将构造函数私有化,在派生类中不可见,无法调用,所有无法构造对象

c++11方式:

cpp 复制代码
class myClass final{
public:
	
private:
	
};

使用final关键字,表示该类不能被继承

单例设计模式

设计模式:

设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化

单例模式

一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。

饿汉模式

不管用不用,程序启动就创建

cpp 复制代码
	//饿汉模式
	class Singleton {
	public:
		//第二步,提供一个静态的方法,提供单例对象
		static Singleton& getInstance() {
			return _sinl;
		}

		void push(int t) {
			_lt.push_back(t);
		}
	private:
		//第一步私有构造函数
		Singleton() {
			//
		}

		//第三步,删除拷贝构造和运算符重载
		Singleton(const Singleton&) = delete;
		Singleton& operator=(const Singleton&) = delete;
		//声明
		static Singleton _sinl;

		list<int> _lt;
	};

	//定义,会调用构造函数
	Singleton Singleton::_sinl;	

代码解释:私有构造函数,是防止外部直接调用对象,创建静态的方法提供获取对象的接口,该对象相同且唯一,同时删除拷贝构造和赋值运算符重载,是为了防止拷贝构造方式创建对象。为了对象唯一,将其声明为静态,同时在类外名定义(调用构造函数,应为声明在类里面,可以调用类里面的构造函数)

饿汉模式的缺点:

1.如果单例对象初始化内容很多,影响启动速度

2.如果两个单例类相互有依赖关系

如A,B两个单例类,要求A先创建,B再创建,B的初始化创建依赖A。

懒汉模式

只有在第一次使用时,才创建实例对象,不用就不创建

cpp 复制代码
namespace lazy {
	//懒汉模式
	class Singleton {
	public:
		//第二步,提供一个静态的方法,提供单例对象
		static Singleton& getInstance() {
			if (_sinl == nullptr) {
				_sinl = new Singleton;
			}
			return *_sinl;
		}

		//一般单例用释放,等到进程结束后,资源自动释放
		//特殊情况:1.中途释放资源,2.需要做一些持续化操作
		static void DelInstance() {
			if (_sinl) {
				delete _sinl;
				_sinl = nullptr;
			}
		}
		void push(string t) {
			_lt.push_back(t);
		}
	private:
		//第一步私有构造函数
		Singleton() {
			//
		}

		~Singleton() {
			//
			//比如讲lt里面的资源写到文件里面
			FILE* fin = fopen("lt.txt", "w");
			for (auto& e : _lt) {
				fputs(e.c_str(), fin);
				fputs("\n", fin);
			}			
		}

		//第三步,删除拷贝构造和运算符重载
		Singleton(const Singleton&) = delete;
		Singleton& operator=(const Singleton&) = delete;
		//声明
		static Singleton* _sinl;

		list<string> _lt;
	};
	Singleton* Singleton::_sinl = nullptr;
}

代码解释:一般来说单例对象不需要释放,因为单例对象整个程序只有之一,随着进程接收,资源释放。但是有写特殊场景1.中途释放资源,2.需要做一些持续化操作。这个时候就需要我们写一个释放资源的静态方法,之所以不直接delete是因为单例类是对象而非指针,指针只是整个类的静态成员,调用 DelInstance内部delete资源,同时可以在析构函数内完成持久化的效果

问题:如果有多个懒汉模式的单例类都需要做持久化,手动的释放调用函数,会十分的麻烦,有什么自动的方法?

可以借助RAII的思想处理:

cpp 复制代码
namespace lazy {
	//懒汉模式
	class Singleton {
	public:
		//第二步,提供一个静态的方法,提供单例对象
		static Singleton& getInstance() {
			if (_sinl == nullptr) {
				_sinl = new Singleton;
			}
			return *_sinl;
		}

		//一般单例用释放,等到进程结束后,资源自动释放
		//特殊情况:1.中途释放资源,2.需要做一些持续化操作
		static void DelInstance() {
			if (_sinl) {
				delete _sinl;
				_sinl = nullptr;
			}
		}
		void push(string t) {
			_lt.push_back(t);
		}
		class GC {
		public:
			~GC() {
				lazy::Singleton::DelInstance();
			}
		};
	private:
		//第一步私有构造函数
		Singleton() {
			//
		}

		~Singleton() {
			//
			//比如讲lt里面的资源写到文件里面
			FILE* fin = fopen("lt.txt", "w");
			for (auto& e : _lt) {
				fputs(e.c_str(), fin);
				fputs("\n", fin);
			}			
		}

		//第三步,删除拷贝构造和运算符重载
		Singleton(const Singleton&) = delete;
		Singleton& operator=(const Singleton&) = delete;
		//声明
		static Singleton* _sinl;

		static GC _gc;

		list<string> _lt;
	};
	Singleton* Singleton::_sinl = nullptr;
	Singleton::GC Singleton::_gc;
}

我们通过使用一个内部类处理,当进程结束后,GC的静态对象会调用销毁函数,销毁函数内部调用隶属于类的static void DelInstance()实现资源的释放和持久化处理

相关推荐
不会C语言的男孩13 分钟前
C++ Primer 第3章:字符串、向量和数组
开发语言·c++
兰令水15 分钟前
leecodecode【反前后指针】【2026.5.31打卡-java版本】
java·开发语言
Dovis(誓平步青云)1 小时前
《QT学习第四篇:常见事件与UDP、TCP、文件系统、(锁、信号量、条件变量》
c语言·开发语言·汇编·qt
AI人工智能+电脑小能手8 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
来杯@Java9 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记9 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥9 小时前
匿名函数 lambda + 高阶函数
java·python·算法
isyangli_blog9 小时前
OpenDayLight (Carbon 版本) 启动与组件安装
开发语言·php
vb20081110 小时前
FastAPI APIRouter
开发语言·python
Benszen10 小时前
KVM虚拟化解决方案
开发语言·perl