求职之路:单例模式详解
最近秋招发现很多公司喜欢问单例模式的内容,在此记录一下自己的学习心得。若有错误之处还望各位能够指出。多谢~~~
什么是单例模式?
定义: 任何情况下只有一个实例。
单例模式的分类
单例模式分为两类:
- 饿汉式: 一开始就将单例类对象实例化完成了。
- 懒汉式: 只有在用的时候才进行实例化
【后面我会对这两种情况进行详细的讲解】
如何实现单例模式?
我们先来看看最简单的单例模式是如何实现的。以饿汉式的非指针版本入手, 后面会一点一点的实现更加安全的单例模式。
饿汉式 - 非指针对象
我们前面提到过,单例模式只能实例化一个对象,也就是说我们不管怎么创建,永远只有这一个对象在被使用。可是我们按照平时的思路,构造函数啥的都是公有的,那么我每次调用一次构造函数不就能创建一个对象了么?这肯定是违背了我们的意愿的,所以我们得把构造函数、复制构造函数、赋值运算符以及析构函数,这些 基本的成员函数都要设计成私有的才行!!!
ok,既然这样我们就先简单写一下我们的类:
class Singleton{
private:
// 将类中的几种默认函数设计成私有的成员函数
Singleton(){
}
Singleton(const Singleton& left){
}
Singleton& operator=(const Singleton& left){
}
~Singleton(){
}
};
构造函数都被变成私有的了,我没法通过构造函数创建要给类对象了。既然如此,那就只能在类中声明一个类对象了,然后通过其他的方式来实例化这个类对象!这个类对象有点特别,它要被其他的所有对象所公用,也就是说大家所指向的都是那一块区域?所以我们应该在类中创建一个什么样的对象才能让它供所有对象共享呢?当然是 static静态成员变量 啦!
那我们继续改进这个类:
class Singleton{
private:
// 声明为静态成员变量,可以供所有的对象共享
static Singleton my_instance;
private:
// 将类中的几种默认函数设计成私有的成员函数
Singleton(){
}
Singleton(const Singleton& left){
}
Singleton& operator=(const Singleton& left){
}
~Singleton(){
}
};
继续,我们已经在类中创建了一个单例类的静态成员变量了,它现在是供所有对象共享的了。但是我们还有一个问题,那就是我怎么样获取到这个对象呢?
那就在类中再添加一个公有的函数,靠这个函数来 返回单例类对象的地址。(这里为啥是地址不是值?朋友啊朋友,这里咋能是值呢?你是像拷贝多份嘛?而且你想拷贝也没有办法给你拷贝啊,我们的复制构造函数和赋值运算符都被声明为私有的了。你在想啥呢?)
没问题了我们就继续。我们能不能将这个函数声明成一个普通的成员函数?不能!为什么?因为普通的成员函数需要成员变量来调用,你的构造函数都不能使用了,你上哪自己构造一个对象出来?我们现在还需要靠这个函数来返回对象的地址呢!所以我们应该将这个成员函数声明成啥?大声说: “静态成员函数”。
为啥是静态成员函数?因为静态成员函数不需要通过成员变量来调用啊~ 我们只需要通过类名::函数名
就能调用啦~
ok,既然这一部分也没问题了,那么我们接着补充完我们的类:
class Singleton{
private:
// 声明为静态成员变量,可以供所有的对象共享
static Singleton my_instance;
private:
// 将类中的几种默认函数设计成私有的成员函数
Singleton(){
}
Singleton(const Singleton& left){
}
Singleton& operator=(const Singleton& left){
}
~Singleton(){
}
public:
// 返回我们的对象指针
static Singleton* getInstance(){
return &my_instance;
}
};
本部分重点:
- 在类中声明类对象,且用关键字static修饰
- 基本成员函数需要必须是私有的
- 函数返回的是类类型指针
- 函数是需要加关键字static
实例:
class Singleton{
private:
// 声明为静态成员变量,可以供所有的对象共享
static Singleton my_instance;
private:
// 将类中的几种默认函数设计成私有的成员函数
Singleton(){
}
Singleton(const Singleton& left){
}
Singleton& operator=(const Singleton& left){
}
~Singleton(){
}
public:
// 返回我们的对象指针
static Singleton* getInstance(){
return &my_instance;
}
// 测试用的代码
void dosth() {
cout << "hello" <<