前言
有一些特殊的类,需要我们单独来学习如何设计。
设计一个不能被拷贝的类
不能被拷贝即封掉:拷贝构造、赋值重载。
- c++ 98
class CopyBan
{
private:
CopyBan(const CopyBan& ban);
CopyBan& operator=(const CopyBan& ban);
};
- c++11
class CopyBan
{
CopyBan(const CopyBan& ban) = delete;
CopyBan& operator=(const CopyBan& ban) = delete;
};
设计一个只能在堆上创建对象的类
构造函数设为私有,防止栈上创建;拷贝、赋值重载全部禁掉
class HeapOnly
{
public:
static HeapOnly* GetHeapOnly()
{
return new HeapOnly;
}
private:
HeapOnly()
{
}
HeapOnly(const HeapOnly& ho) = delete;
HeapOnly& operator=(const HeapOnly& ho) = delete;
};
设计一个类只能在栈上创建对象
要禁掉new和delete关键字的时候,new的返回值必须指定为void*;delete的参数也必须指定。
class StackOnly
{
public:
static StackOnly GetHeapOnly()
{
return StackOnly();
}
private:
StackOnly()
{
}
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;
};
设计一个不能被继承的对象
- c++98
在继承体系里,子类初始化必须调父类的构造函数,因此只要封死父类的构造函数,就可以完成设计
- c++11
在c++11中,给类加final关键字即表示该类不可以被继承。
class NoExtend final
{
};
设计一个类,只能创建一个对象(单例模式)
- 懒汉
懒汉即第一次使用的时候才创建对象。
#include <mutex>
class Lazy
{
public:
static Lazy* GetInstance()
{
//因为只会创建一次,避免反复申请锁
//双重判断提高效率保证安全
if (_ptr == nullptr)
{
imtx.lock();
if (_ptr == nullptr)
{
_ptr = new Lazy();
}
imtx.unlock();
}
return _ptr;
}
//因为是指针,所以设计一个内部的、
//垃圾回收类
class GC
{
public:
~GC()
{
if (_ptr)
{
delete _ptr;
}
}
};
static GC gc;
private:
Lazy()
{
}
static Lazy* _ptr;
mutex vtx;//保护类内资源
static mutex imtx;//保护实例对象
};
Lazy* Lazy::_ptr = nullptr;
mutex Lazy::imtx;//不需要给值,但要在外面定义一下
- 饿汉
class Starve
{
public:
static Starve* getInstance()
{
return _ptr;
}
private:
Starve()
{
}
static Starve* _ptr;
};
//在main函数之前就创建好了
Starve* Starve::_ptr = new Starve;
优缺点分析:
懒汉:
优点:进程启动没有负载;多个单例可以控制顺序启动。
缺点:实现比较麻烦
饿汉:
优点:简单
缺点:启动慢;读取顺序无法确定(多个线程去启动多个单例)。