一、设计一个不能拷贝的类
核心思想
禁止调用拷贝构造 + 赋值运算符重载。
1. C++98 方式(私有化+只声明不定义)
cpp
class CopyBan
{
private:
// 只声明,不实现 + 设为私有
CopyBan(const CopyBan&);
CopyBan& operator=(const CopyBan&);
};
2. C++11 方式(=delete)
cpp
class CopyBan
{
public:
// 删除默认拷贝函数
CopyBan(const CopyBan&) = delete;
CopyBan& operator=(const CopyBan&) = delete;
};
二、设计一个只能在堆上创建的类
核心思想
- 构造函数私有
- 禁用拷贝(防止在栈上拷贝出对象)
- 提供静态工厂方法在堆上创建对象
cpp
class HeapOnly
{
public:
static HeapOnly* CreateObject()
{
return new HeapOnly;
}
private:
// 1. 构造函数私有
HeapOnly() {}
// 2. 防拷贝
HeapOnly(const HeapOnly&) = delete;
};
使用方式
cpp
HeapOnly* obj = HeapOnly::CreateObject();
三、设计一个只能在栈上创建的类
核心思想
- 构造函数私有
- 禁用
operator new(禁止在堆上创建) - 静态方法返回栈上临时对象
cpp
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
// 禁掉 new / delete
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;
private:
// 构造私有
StackOnly() : _a(0) {}
int _a;
};
使用方式
cpp
StackOnly obj = StackOnly::CreateObj();
四、设计一个无法被继承的类
1. C++98 方式(构造私有)
cpp
class NonInherit
{
public:
static NonInherit GetInstance()
{
return NonInherit();
}
private:
NonInherit() {} // 派生类无法调用构造
};
2. C++11 方式(final 关键字)
cpp
class A final
{
// 该类不能被继承
};
五、设计一个只能创建一个对象的类(单例模式)
概念
一个类永远只能创建一个实例,全局唯一。
1. 饿汉模式(Eager)
特点
- 程序启动时就创建对象
- 绝对线程安全
- 简单粗暴
cpp
class Singleton
{
public:
static Singleton& GetInstance()
{
return m_instance;
}
private:
// 构造私有
Singleton() {}
// 防拷贝
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 静态对象,程序启动即初始化
static Singleton m_instance;
};
// 初始化
Singleton Singleton::m_instance;
优点
- 线程安全
- 简单
- 无锁
缺点
- 进程启动慢
- 多个单例初始化顺序不可控
2. 懒汉模式(Lazy)
特点
- 第一次使用时才创建
- 延迟加载
- 必须保证线程安全(双检查锁)
cpp
class Singleton2
{
public:
static Singleton2* GetInstance()
{
// 双检查锁 DCL
if (m_pInstance == nullptr)
{
m_mtx.lock();
if (m_pInstance == nullptr)
{
m_pInstance = new Singleton2();
}
m_mtx.unlock();
}
return m_pInstance;
}
// 垃圾回收(自动释放)
class CGarbo
{
public:
~CGarbo()
{
if (m_pInstance)
delete m_pInstance;
}
};
static CGarbo Garbo;
private:
Singleton2() {}
Singleton2(const Singleton2&) = delete;
Singleton2& operator=(const Singleton2&) = delete;
static Singleton2* m_pInstance;
static mutex m_mtx;
};
// 静态变量初始化
Singleton2* Singleton2::m_pInstance = nullptr;
mutex Singleton2::m_mtx;
Singleton2::CGarbo Singleton2::Garbo;
优点
- 进程启动快
- 延迟初始化
- 多单例可控制顺序
缺点
- 复杂
- 需考虑线程安全
六、总结
| 需求 | 核心方法 |
|---|---|
| 不能拷贝 | 禁拷贝构造 + 赋值重载 |
| 只能在堆上 | 构造私有 + 静态工厂返回 new |
| 只能在栈上 | 禁 new + 静态工厂返回栈对象 |
| 不能被继承 | final / 构造私有 |
| 单例模式 | 饿汉(启动创建)/ 懒汉(首次创建) |
七、完整代码(笔记版可直接运行)
cpp
#include<iostream>
#include <mutex>
#include <thread>
using namespace std;
// 1. 不能拷贝
class CopyBan
{
CopyBan(const CopyBan&) = delete;
CopyBan& operator=(const CopyBan&) = delete;
};
// 2. 只能在堆上
class HeapOnly
{
public:
static HeapOnly* CreateObject()
{
return new HeapOnly;
}
private:
HeapOnly() {}
HeapOnly(const HeapOnly&) = delete;
};
// 3. 只能在栈上
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;
private:
StackOnly() :_a(0) {}
int _a;
};
// 4. 不能被继承
class A final
{};
// 5. 单例模式
// 饿汉
class Singleton
{
public:
static Singleton& GetInstance()
{
return m_instance;
}
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton m_instance;
};
Singleton Singleton::m_instance;
// 懒汉
class Singleton2
{
public:
static Singleton2* GetInstance()
{
if (nullptr == m_pInstance)
{
m_mtx.lock();
if (nullptr == m_pInstance)
{
m_pInstance = new Singleton2();
}
m_mtx.unlock();
}
return m_pInstance;
}
class CGarbo
{
public:
~CGarbo()
{
if (Singleton2::m_pInstance)
delete Singleton2::m_pInstance;
}
};
static CGarbo Garbo;
private:
Singleton2() {}
Singleton2(const Singleton2&) = delete;
Singleton2& operator=(const Singleton2&) = delete;
static Singleton2* m_pInstance;
static mutex m_mtx;
};
Singleton2* Singleton2::m_pInstance = nullptr;
mutex Singleton2::m_mtx;
Singleton2::CGarbo Singleton2::Garbo;