目录
1.实现一个只能在堆上创建对象的类(了解思想)
2.实现一个只能在栈上创建对象的类(同样思想最重要)
3.单例模式(有实际应用价值)
实现原理:为了不开出静态变量和在栈上开变量有两种方式
方式一:将析构函数私有,然后手动实现一个有析构功能的成员函数,调用该函数即可。
方式二:将构造函数私有,然后手动实现一个返回new出来对象的成员函数。比较坑的是,要注意将拷贝构造和赋值都屏蔽掉。因为,在用拷贝构造和赋值时,还会使用构造函数。
方式一:
#includeusing namespace std;//方式1
class HeapOnly
{
public:void Delete() //手动实现释放{cout << "Delete by myself" << endl;delete this;}
private:~HeapOnly() //析构私有{}int _a;
};
int main()
{HeapOnly h1;static HeapOnly h2;HeapOnly* h3 = new HeapOnly;h3->Delete();return 0;
}
不屏蔽静态和栈上的会报错 。
方式二:
//方式二
class HeapOnly
{
public:static HeapOnly* GetRet() //手动new一个返回{cout << "new by myself" << endl;HeapOnly* ret=new HeapOnly;return ret;}HeapOnly(const HeapOnly& hp) = delete; //屏蔽拷贝构造和赋值HeapOnly operator=(const HeapOnly& hp) = delete;private:HeapOnly() //构造私有{}int _a;
};
int main()
{//HeapOnly h1;//static HeapOnly h2;HeapOnly* h = HeapOnly::GetRet();return 0;
}
由于,栈不能和堆一样手动写一个函数进行销毁。因此只能私有构造函数。
class StackOnly
{
private:int _a;StackOnly():_a(0){}
public:static StackOnly GetRet(){cout << "get by myself" << endl;StackOnly ret;return ret;}//上面涉及拷贝(传值返回),所以不能禁用拷贝,因此解决不了创建静态对象的问题。。/*StackOnly(const StackOnly& st) = delete;StackOnly operator=(const StackOnly& st) = delete;*/void* operator new(size_t n) = delete; //可以把new对象屏蔽。
};
int main()
{//HeapOnly h1;//static HeapOnly h2;/*HeapOnly* h = HeapOnly::GetRet();*/StackOnly st1 = StackOnly::GetRet();//StackOnly* st2 = new(StackOnly);return 0;
}
单例模式是指一个类只能创建一个对象。这个实例可以被全局访问,被所有模块共享。
实现方式1:饿汉模式
饿汉指的是,无论你是否使用该实例,程序启动就创建一个实例对象。
class singleton
{
public: singleton* GetInstance(){return &m_instance; //方便拿出_instance}singleton(const singleton& sl) = delete; //屏蔽掉拷贝和赋值singleton operator=(const singleton& sl) = delete;private:singleton() //只能实例化一次,因此构造一定要私有。:_a(0){}static singleton m_instance; //静态初始化成员,方便马上直接拿出来。int _a;
};singleton singleton::m_instance; //在主程序开始前就实例化int main()
优点:简单,不存在线程安全的问题。
缺点:拖延程序启动时间,如果有多个单例模式初始化的单例顺序不一定准。
实现方式2:懒汉模式
懒汉指的是,第一次使用对象时再实例化。
class MemoryPool
{
public:static MemoryPool* GetInstance(){if (_pinst == nullptr){_pinst = new MemoryPool; //用时初始化一次}return _pinst;}class CGarbo { //内嵌垃圾回收类public:~CGarbo(){if (_pinst)delete _pinst;}};
private:MemoryPool() //只能实例化一次,因此构造一定要私有。{}char* _ptr=nullptr;static MemoryPool* _pinst;
};MemoryPool* MemoryPool::_pinst = nullptr; //创建单例对象
static MemoryPool::CGarbo gc; //通过调用内嵌类的析构实现资源释放。
优点:不会拖延程序启动时间,可以确定单例对象实例的循序。
缺点:复杂,存在线程安全的问题。