[c++ practice road] class design

foreword

There are some special classes that require us to learn how to design alone.

Design a class that cannot be copied

It cannot be copied or sealed: copy construction, assignment overloading.

  • 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;
};

Design a class that can only create objects on the heap

The constructor is set to private to prevent creation on the stack; copying, assignment and overloading are all banned

class HeapOnly
{
    
    
public:
	static HeapOnly* GetHeapOnly()
	{
    
    
		return new HeapOnly;
	}
private:
	HeapOnly()
	{
    
    

	}

	HeapOnly(const HeapOnly& ho) = delete;
	HeapOnly& operator=(const HeapOnly& ho) = delete;
};

Design a class that can only create objects on the stack

To disable the new and delete keywords, the return value of new must be specified as void*; the parameters of delete must also be specified.

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

	}
	void* operator new(size_t size) = delete;
	void operator delete(void* p) = delete;
};

Design an object that cannot be inherited

  • c++98

In the inheritance system, the initialization of the subclass must adjust the constructor of the parent class , so as long as the constructor of the parent class is sealed, the design can be completed

  • c++11

In C++11, adding the final keyword to a class means that the class cannot be inherited.

class NoExtend final
{
    
    

};

Design a class, only one object can be created (singleton mode)

  • lazy man

The lazy man creates the object when it is used for the first time.

#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;//不需要给值,但要在外面定义一下
  • hungry man
class Starve
{
    
    
public:
	static Starve* getInstance()
	{
    
    
		return _ptr;
	}
private:
	Starve()
	{
    
    

	}

	static Starve* _ptr;
};
//在main函数之前就创建好了
Starve* Starve::_ptr = new Starve;

Advantages and disadvantages analysis:

Lazy:

Pros: There is no load on process startup; multiple singletons can control sequential startup.
Disadvantages: more troublesome to implement

Hungry man:

Advantages: Simple
Disadvantages: Slow startup; the reading order cannot be determined (multiple threads to start multiple singletons).

Guess you like

Origin blog.csdn.net/m0_73209194/article/details/131709138