不能背拷贝的类
不能调用拷贝构造和赋值运算符重载
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()实现资源的释放和持久化处理