C++进阶(13)特殊类设计

一、请设计一个类,不能被拷贝

类的拷贝只会在两个场景中出现:一个是构造的时候—拷贝构造,另一个则是赋值的时候。

所以只需要将这两种函数禁止用户访问即可。

第一种:私有化

// 将拷贝构造和赋值重载进行私有化,这样用户就访问不到。
class CopyBan
{
private:
	int _a;
	std::string _b;
private:
	CopyBan(const CopyBan&) {}
	CopyBan operator=(const CopyBan&) {}
public:
	CopyBan(int a = 0, std::string b = "none") {}
};

第二种:禁用delete

// 直接将拷贝构造和赋值重载禁用掉即可。
class CopyBan
{
private:
	int _a;
	std::string _b;
public:
	CopyBan(int a = 0, std::string b = "none") {}
	CopyBan(const CopyBan&) = delete;
	CopyBan operator=(const CopyBan&) = delete;
};

二、请设计一个类,只能在堆上创建

如果想要用户只能在堆上创建类的话,那就不能让用户直接访问到构造函数和赋值拷贝,因为这种默认的方式都是在栈上创建类对象的。

// 仅提供一个自定义的构造函数,让用户只能通过该接口创建类,这样就能保证只在堆上创建了。
class HeapOnly
{
private:
	int _a;
	std::string _b;
private:
	HeapOnly(int a = 0, std::string b = "none")
		:_a(a)
		,_b(b)
	{}
	HeapOnly(const HeapOnly&) = delete;
	HeapOnly operator=(const HeapOnly&) = delete;
public:
	HeapOnly* HeapCreate(int a = 0, std::string b = "none")
	{
		HeapOnly* ho = new HeapOnly(a, b);
		return ho;
	}
};

三、请设计一个类,只能在栈上创建对象

因为只能在栈上创建,所以只需要将new和delete禁用或者私有化即可。

class StackOnly
{
private:
	int _a;
	std::string _b;
private:
	 私有化
	//void* operator new(size_t) {};
	//void operator delete(void*) {};
public:
	// 禁用
	void* operator new(size_t) = delete;
	void operator delete(void*) = delete;
};

四、请设计一个类,不能被继承

如果一个类不能被继承的化,可以用final关键字进行修饰这个类;也可以将该类的构造函数进行私有化,在派生类构造中,钓不到基类的构造,间接的禁止该类被继承。

第一种:私有化

class NoInherit
{
private:
	int _a;
	std::string _b;
private:
	NoInherit(int a = 0, std::string b = "none")
		:_a(a)
		,_b(b)
	{}
public:
	static NoInherit Create(int a = 0, std::string b = "none")
	{
		return NoInherit(a, b);
	}
};

第二种:final关键字

class NoInherit final
{
private:
	int _a;
	std::string _b;
public:
	NoInherit() {}
};

五、请设计一个类,只能创建一个对象(单例模式)

单例模式:就是只能创建一个对象。

单例模式分为两种:饿汉模式,懒汉模式。

饿汉模式:

不管将来用不用,程序启动时就创建一个唯一的实例对象。

// 饿汉模式
// 优点:简单
// 缺点:可能会导致进程启动慢,且如果有多个单例类对象实例启动顺序不确定。

class EagerInitialization
{
private:
    // 声明一个静态的对象
	static EagerInitialization _instance;
private:
    // 构造函数私有化
	EagerInitialization() 
	{ 
		std::cout << "Singleton instance created" << std::endl; 
	}
public:
    // 返回实例
	static EagerInitialization* GetInstance()
	{
		return &_instance;
	}
    // 禁用拷贝构造和赋值重载
	EagerInitialization(const EagerInitialization&) = delete;
	EagerInitialization& operator=(const EagerInitialization&) = delete;
};
// 定义一个静态对象
EagerInitialization EagerInitialization::_instance;

懒汉模式:

延迟加载,当需要用到时,才创建对象。

不支持线程安全:

class LazyInitialization
{
private:
    // 声明静态对象
	static LazyInitialization* _instance;
    // 构造函数私有化
	LazyInitialization() {}
public:
    // 延迟加载,得到_instance
	LazyInitialization* GetInstance()
	{
		if (_instance == nullptr)
		{
			_instance = new LazyInitialization();
		}
		return _instance;
	}
    // 禁用拷贝构造和赋值重载
	LazyInitialization(const LazyInitialization&) = delete;
	LazyInitialization& operator=(const LazyInitialization&) = delete;
};
// 初始化对象
LazyInitialization* LazyInitialization:: _instance = nullptr;

支持线程安全:

// 支持线程安全
class LazyInitialization
{
private:
    // 声明静态对象和锁
	static LazyInitialization* _instance;
	static std::mutex mtx;
     // 构造函数私有化
	LazyInitialization() {}
public:
    // 延迟加载,得到_instance
	LazyInitialization* GetInstance()
	{
		if (_instance == nullptr)
		{	
            // 自动加锁解锁,保证开辟空间的操作是原子的
			std::lock_guard<std::mutex> lg(mtx);
			if (_instance == nullptr)
				_instance = new LazyInitialization();
		}
		return _instance;
	}
    // 禁用拷贝构造和赋值重载
	LazyInitialization(const LazyInitialization&) = delete;
	LazyInitialization& operator=(const LazyInitialization&) = delete;
};
// 初始化对象和锁
LazyInitialization* LazyInitialization:: _instance = nullptr;
std::mutex LazyInitialization::mtx;

谢谢大家!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仍有未知等待探索

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值