文章目录

  • ​​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,实际上只构造了一个对象,但是目前析构函数没有调用,可能会造成资源泄漏问题

(P18)对象的使用:static与单例模式 ,实现单例模式应该注意的点_#include

  • 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;
}
  • 测试:
    释放方法1

    释放方法2

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中任何成员以及方法;

  • eg:
#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