(P18)对象的使用:static与单例模式 ,实现单例模式应该注意的点
原创
©著作权归作者所有:来自51CTO博客作者喜欢打篮球的普通人的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
- 1.static与单例模式
- 2.实现单例模式应该注意的点
- 3.static成员函数可以访问类内成员的方法
1.static与单例模式
- 特点:
(1)保证一个类只有一个实例,并提供一个全局访问点
保证一个程序只有一个类的实例,只有一个对象
(2)禁止拷贝 - eg:18cpp\18cpp\18cpp\01.cpp
Singleton是单例模式实现了一个类
#include <iostream>
using namespace std;
class Singleton
{
public:
//GetInstance成员函数可以访问Singleton私有的构造函数
static Singleton* GetInstance()
{
if (instacne_ == NULL)
{
instacne_ = new Singleton;//new:创建一个类的实例
}
return instacne_;
}
~Singleton()
{
cout<<"~Singleton ..."<<endl;
}
private:
//禁止拷贝就是将拷贝构造函数,等号运算符声明为私有的,就可以保证不进行拷贝构造,也不能赋值
//禁止拷贝1:禁止调用拷贝构造函数
//将拷贝构造函数声明为私有的,且不提供她的实现
Singleton(const Singleton& other);
//禁止拷贝2:
//将赋值操作声明为私有的,禁止赋值操作
Singleton& operator=(const Singleton& other);
//将构造函数声明为私有的,在main函数中就不能调用构造函数
Singleton()
{
cout<<"Singleton ..."<<endl;
}
static Singleton* instacne_;//仅仅声明
};
Singleton* Singleton::instacne_;//定义性的说明
int main(void)
{
//Singleton s1;
//Singleton s2;
//不论调用几次GetInstance,总是返回同一个对象,同一个实例
//如何验证他们是同一个实例?只需查看s1和s2指针所指向的地址是否一致
Singleton* s1 = Singleton::GetInstance();
Singleton* s2 = Singleton::GetInstance();
//Singleton s3(*s1); // 调用拷贝构造函数
//s4=s2
return 0;
}
- 测试:
说明2次GetInstance返回的是同一个实例,保证一个程序只有一个实例;
可以在多个模块调用GetInstance,返回的总是同一个实例,相当于该实例是一个全局变量,GetInstance是全局的访问点来获取全局变量
虽然调用了2次的GetInstance,实际上只构造了一个对象,但是目前析构函数没有调用,可能会造成资源泄漏问题

- eg2:18cpp\18cpp\18cpp\02.cpp
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* GetInstance()
{
if (instacne_ == NULL)
{
instacne_ = new Singleton;
}
return instacne_;
}
~Singleton()
{
cout<<"~Singleton ..."<<endl;
}
//释放方法1
//static void Free()
//{
// if (instacne_ != NULL)
// {
// delete instacne_;
// }
//}
//释放方法2
//Garbo功能:垃圾回收
//嵌套类
class Garbo
{
public:
~Garbo()
{
if (Singleton::instacne_ != NULL)
{
delete instacne_;
}
}
};
private:
Singleton(const Singleton& other);
Singleton& operator=(const Singleton& other);
Singleton()
{
cout<<"Singleton ..."<<endl;
}
static Singleton* instacne_;
//释放方法2
//garbo_对象在生命周期结束的时候,会自动调用析构函数,达到销毁单例模式对象的目的
//利用的是确定性析构的原则
static Garbo garbo_; // 利用对象的确定性析构
};
//释放方法2
Singleton::Garbo Singleton::garbo_;//Singleton::Garbo 是类型,Singleton表示garbo_是Singleton的一个成员
Singleton* Singleton::instacne_;
int main(void)
{
//Singleton s1;
//Singleton s2;
Singleton* s1 = Singleton::GetInstance();
Singleton* s2 = Singleton::GetInstance();
//Singleton s3(*s1); // 调用拷贝构造函数
//释放方法1
// Singleton::free();
return 0;
}
2.实现单例模式应该注意的点
- (1)要把构造函数私有化,让外部不能实例化对象
- (2)需要提供一个静态的全局访问点
- (3)禁止拷贝,如果是拷贝的,则不能确保整个程序只有一个对象
- eg3:18cpp\18cpp\18cpp\03.cpp
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton& GetInstance()//返回的是引用,所以不会调用拷贝构造函数
{
static Singleton instance; // 局部静态对象:是在运行期初始化,是有状态的
return instance; //第2次调用时,会返回先前所初始化的实例,以此来保证单例
}
//写法2
// static Singleton* GetInstance()
// {
// static Singleton instance;
// return &instance;
// }
~Singleton()
{
cout<<"~Singleton ..."<<endl;
}
private:
Singleton(const Singleton& other);
Singleton& operator=(const Singleton& other);
Singleton()
{
cout<<"Singleton ..."<<endl;
}
};
int main(void)
{
Singleton& s1 = Singleton::GetInstance();
Singleton& s2 = Singleton::GetInstance();
//写法2
// Singleton* s1 = Singleton::GetInstance();
// Singleton* s2 = Singleton::GetInstance();
return 0;
}
- 测试:
目前最好的单例模式实现方式,但不是线程安全的单例模式类的实现
3.static成员函数可以访问类内成员的方法
- ref:能不能在static方法中访问对象的private成员?
总结: 访问权限应该看类,而不是盯着对象看private,其他类不能访问该类对象的private成员
所以,一看对象,二看类,要访问对象的成员,先看对象所处的类!
只要你在类Test中的任何一个方法中,创建一个Test对象,你都能够随意访问类Test中任何成员以及方法;
#include <cstdio>
#include <memory>
#include <vector>
#include <iostream>
using namespace std;
struct Test{
Test():m_num(1){}
static Test instance()
{
auto t = Test();
std::cout<<"AAAL: "<<t.m_num<<std::endl;
return t;
}
void print()
{
auto t = instance();
t.m_num=100;
std::cout<<t.m_num
<<std::endl;
}
private:
int m_num;
};
int main()
{
/*
shared_ptr<int> p1(new int(1));
shared_ptr<shared_ptr<int>> p2=std::make_shared<shared_ptr<int>>(p1);
*p1=200;
std::cout<<*(*p2)<<std::endl;
*/
Test t;
t.print();
}
wangji@script-wang:~/code/test/broudcast$ "/home/wangji/code/test/broudcast/test7.exe"
AAAL: 1
100