C++ 特殊类设计:只能在堆、栈上创建的类、无法继承的类、无法拷贝的类、只能创建一个对象的类


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

拷贝只会通过拷贝构造函数和赋值运算符重载来实现,所以只需要让该类无法调用这两样东西即可

class CopyBan
{
public:
private:
	/*
	c++98写法,私有化后外界就无法调用
	CopyBan(const CopyBan&);
	CopyBan& operator=(const CopyBan&);
	*/
	//c++11写法
	CopyBan(const CopyBan&) = delete;
	CopyBan& operator=(const CopyBan&) = delete;
};

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

要想让一个类不能被继承,则只需要让子类无法调用他的构造函数即可

class NonInherit
{
public:
	static NonInherit CreateObject()
	{
		return NonInherit();
	}
private:
	//构造函数私有化,子类无法调用构造函数,所以无法继承
	NonInherit()
	{}
};

在C++11中引入了关键字final,也可以直接使用final来禁止继承

class NonInherit final
{};

请设计一个类,只能在堆上创建对象

首先要做的就是将构造函数私有化,并且防拷贝,防止其他人在栈上生成对象。
接着提供一个接口,在堆中创建对象后将指向对象的指针返回。这个接口必须要是静态的,因为要调用成员函数必须要通过一个对象, 而因为我们禁用了构造函数和拷贝,无法创建对象,所以只能声明为静态函数让其通过类域来调用这个接口。

namespace lee
{
	class HeapOnly
	{
	public:
		static HeapOnly* CreateObject()
		{
			return new HeapOnly();
		}

	private:
		HeapOnly()
		{}

		//c++11,防拷贝
		HeapOnly(const HeapOnly&) = delete;
		HeapOnly& operator=(const HeapOnly&) = delete;

		/*
		c++98写法
		HeapOnly(const HeapOnly&);
		HeapOnly& operator=(const HeapOnly&);
		*/

	};
};

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

思路同上, 直接提供一个创建对象的接口即可

class StackOnly
{
public:
	static StackOnly CreateObject()
	{
		return StackOnly();
	}
private:
	StackOnly()
	{}
};

还有一种做法,就是屏蔽new,因为new在底层会调用operator new,所以只需要将他禁用即可。

但是这种方法是有缺陷的,虽然禁用了在堆上创建对象,但是还可以在静态区创建对象,所以并不是只能在栈上创建对象的类。

class StackOnly
{
public:
	StackOnly()
	{}
private:
	void* operator new(size_t size) = delete;
	void operator delete(void* p) = delete;
	
};

请设计一个类,只能创建一个对象

一个类只能创建一个对象,也就是单例模式。
在上一篇中介绍过单例模式的思路,这里就不赘述了
设计模式 单例模式 :懒汉、饿汉模式实现线程安全的单例模式(C++)

饿汉模式

class EagerSingleton
{
public:
	//提供给外界一个唯一的对象
	static EagerSingleton* GetInstance()
	{
		return &_inst;
	}


	EagerSingleton& operator=(const EagerSingleton&) = delete; //c++11写法,为了防止拷贝,直接把拷贝构造和赋值运算符删除
	EagerSingleton(const EagerSingleton&) = delete;
private:
	//构造函数私有化,此时只能创建静态对象。
	EagerSingleton()
	{};

	/*
	c++98写法,将成员函数私有化,使得外界无法调用
	EagerSingleton& operator=(const EagerSingleton&);
	EagerSingleton(const EagerSingleton&);
	*/

	static EagerSingleton _inst;
	//使用静态的成员,因为静态成员属于整个类域,是唯一的一份。在程序开始阶段创建之后,其他人获取时只需要返回指向这个对象的指针即可
};

EagerSingleton EagerSingleton::_inst; //程序启动时则创建对象

懒汉模式

class LazySingleton
{
public:
	//获取对象
	static LazySingleton* GetInstance()
	{
		//双重检查,第一重检验是否创建对象,防止不必要的加锁
		if (_inst == nullptr)
		{
			//第二重检验保证线程安全
			//_mtx.lock();
			std::unique_lock<std::mutex> lock(_mtx);//RAII保证因异常抛出导致的安全问题
			if (_inst == nullptr)
			{
				_inst = new LazySingleton;
			}
			//_mtx.unlock();
		}
		return _inst;
	}

	//删除对象
	static void DelInstance()
	{
		std::unique_lock<std::mutex> lock(_mtx);

		delete _inst;
		_inst = nullptr;
	}

	//运用RAII的思想内嵌一个GC类,程序结束时自动调用析构函数来释放单例对象
	class GC
	{
	public:
		~GC()
		{
			LazySingleton::DelInstance();
		}
	};
	static GC gc;

	LazySingleton& operator=(const LazySingleton&) = delete; //c++11写法,为了防止拷贝,直接把拷贝构造和赋值运算符删除
	LazySingleton(const LazySingleton&) = delete;
private:

	LazySingleton()
	{};

	/*
	c++98写法,将成员函数私有化,使得外界无法调用
	LazySingleton& operator=(const LazySingleton&);
	LazySingleton(const LazySingleton&);
	*/

	static LazySingleton* _inst;
	static std::mutex _mtx;
};

LazySingleton::GC gc;
LazySingleton* LazySingleton::_inst = nullptr;
std::mutex LazySingleton::_mtx;

猜你喜欢

转载自blog.csdn.net/qq_35423154/article/details/107643839