设计不能被拷贝的类
c++11是下边的用法,c++98就是将拷贝构造变成私有,并且只声明并不实现
1 2 3 4 5 6 7 8 9 10
   | class A { public: 	A(int val):_val(val){} 	A(const A& a) = delete; 	A& operator=(const A& a) = delete; private: 	int _val; };
 
   | 
 
设计只能在堆上创建的类
方案1、将析构函数私有化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | class HeapOnly { public: 	void destroy() 	{ 		delete this; 	} private: 	~HeapOnly(){} }; int main() { 	HeapOnly* hp = new HeapOnly; 	hp->destroy(); 	return 0;  }
   | 
 
方案2、构造函数私有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | class HeapOnly { public: 	static HeapOnly* CreatObj() 	{ 		return new HeapOnly; 	} 	 	HeapOnly(const HeapOnly& hp) = delete; private: 	HeapOnly(){} }; int main() { 	HeapOnly* hp = HeapOnly::CreatObj(); 	delete hp; 	return 0;  }
   | 
 
注意:也要把拷贝构造给删除掉
设计只能在栈上创建的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | class StackOnly { public: 	static StackOnly CreatObj() 	{ 		return StackOnly(); 	} private: 	StackOnly() {} }; int main() { 	StackOnly sk = StackOnly::CreatObj(); 	 	static StackOnly copy(sk); 	StackOnly* copy2 = new StackOnly(sk); 	return 0;  }
   | 
 
解决new
1 2 3 4 5 6 7 8 9 10 11
   | class StackOnly { public: 	static StackOnly CreatObj() 	{ 		return StackOnly(); 	} 	void* operator new(size_t n) = delete; private: 	StackOnly() {} };
   | 
 
但是静态区的拷贝构造还是不能被禁止。
设计不能被继承的类
1 2 3 4 5 6 7 8 9 10 11
   |  class NonInherit   {   public:   	static NonInherit GetInstance()   	{   		return NonInherit();   	}   private:   	NonInherit(){}   };
 
  | 
 
在C++11中有了final关键字,修饰类就说明该类不能被继承。
设计只能创建一个对象的类(单例)
饿汉模式
构造函数私有,在静态区创建一个对象,
- 简单,没有线程安全问题
 
- 一个程序中,多个单例,并且有先后创建初始化的顺序要求时,饿汉无法控制,比如多个文件,就无法控制顺序
 
- 饿汉的单例类,初始化时任务多,会影响程序的启动速度。
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | class A { public: 	static A* getInstance() 	{ 		return _a; 	} 	void fun() 	{ 		std::cout << "调用fun()\n"; 	} private: 	A(){} 	static A* _a; };
  A* A::_a = new A;
 
  int main() { 	A* p = A::getInstance(); 	p->fun(); }
   | 
 
懒汉模式
第一次使用对象再创建实例对象
- 可以控制创建的顺序
 
- 不影响启动速度
 
- 相对复杂,有线程安全问题
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   | class A { public: 	static A* getInstance() 	{ 		if(_a == nullptr) 		{ 			_a = new A; 		} 		return _a; 	} 	void fun() 	{ 		std::cout << "调用fun()\n"; 	}
  	 	class CGarbo { 	public: 		~CGarbo() 		{ 			if (_a) 				delete _a; 		} 	};
  private: 	A(){} 	static A* _a; };
  A* A::_a = nullptr;
  static A::CGarbo gc;
  int main() { 	A* p = A::getInstance(); 	p->fun(); }
   | 
 
单例对象释放
- 一般情况下,单例对象不需要释放,因为一般整个程序运行期间都可能用它
 
- 单例对象在进程正常结束后,也会资源释放
 
- 有些特殊场景需要释放,比如单例对象析构时,要进行一些持久化操作(往文件数据库写)操作
 
- 释放时,可以做个内部类,如上边代码