设计模式之单例类——如何让一个类只实例化一个对象

标签: 对象 实例
1527人阅读 评论(0) 收藏 举报
分类:

其实这是一道面试题。
这道题的思路是,我只让这个类通过一个公有函数实例化对象,即可以将构造函数设置为私有成员函数。

include <iostream>
using namespace std;

class Single
{
public:

    static Single& SingleCreate()
    {
        if (m == NULL)
        {
            m = new Single();
        }
            return *m;
    }
    ~Single()
    {
        delete m;
    }

    Single(const Single &a)
    {
    if (m == NULL)
    {
    m = new Single();
    }
    }

private:
    Single()
    {}
    static  Single *m;
};

Single* Single::m = NULL;

int main()
{
    Single a = Single::SingleCreate();
}

这是我第一次写出的代码,我本来认为这样就可以了,结果经过我的调试,发现这样写是有问题的。
这里写图片描述

通过上面的图片可以看出,我们实例化的a的地址,跟在SingleCreate函数中返回的m的值是不同的,即这个类实例化了两个对象,这样就偏题了。
经过分析,我们现在来看SingleCreate函数

    static Single& SingleCreate()
    {
        if (m == NULL)
        {
            m = new Single();
        }
            return *m;
    }

这里retuen 的*m,会自动生成拷贝构造函数,因为return *m是返回一个对象,这里是返回临时变量,自动调用拷贝构造函数,因为我们没有定义拷贝构造函数,所以这里会自动生成一个拷贝构造函数。
所以达不到只实例化一个对象的目的
经过上面的分析,经代码优化为


class Single
{
public:


    static Single* SingleCreatePtr()
    {
        if (m == NULL)
        {
            m = new Single();
        }
        return m;
    }
    ~Single()
    {
        delete m;
    }


private:
    Single()
    {}

    static  Single *m;
};
Single* Single::m = NULL;
int main()
{
    Single *a = Single::SingleCreatePtr();
}

这个时候经过调试,得到下面
这里写图片描述
这个时候就得到的是一个对象。因为传指针的实质是在传地址,不会产生临时变量。
现在已经解决了在返回值时只实例化一个对象的问题
接下来看第三个问题
三、构造函数
接下来我们在main函数中加这么一句话:

Single *b = a;

这个时候会发生什么呢?
对,会实例化出另一个对象,这是因为编译器自动生成了赋值构造函数,就像上面的拷贝构造函数一样,都是编译器自动生成并调用的,那么如何防止这些情况的发生?
我的方法是在类中只声明不定义拷贝构造函数以及赋值构造函数。

class Single
{
public:

    static Single& SingleCreate()
    {
        if (m == NULL)
        {
            m = new Single();
        }
            return *m;
    }
    static Single* SingleCreatePtr()
    {
        if (m == NULL)
        {
            m = new Single();
        }
        return m;
    }
    ~Single()
    {
        delete m;
    }


private:
    Single()
    {}
    Single(const Single &a);
    Single& operator = (const Single &a);
    static  Single *m;
};

即将拷贝构造函数和赋值运算符重载函数都变成私有的成员函数,在外不可调用,就避免了因为构造函数多实例化对象的情况。
四、通过静态局部变量

class Single  
{  
private:  
    Single()   //构造函数是私有的  
    {  
    }  
public:  
    static Single & GetInstance()  
    {  
        static Single instance;   //局部静态变量  
        return instance;  
    }  
};  

静态局部变量在GetInstance函数中被定义,初始化为0,且静态局部变量存放在内存的全局数据区。函数结束时,静态局部变量不会消失,每次该函数调用 时,也不会为其重新分配空间。它始终驻留在全局数据区,直到程序运行结束。静态局部变量的初始化与全局变量类似.如果不为其显式初始化,则C++自动为其 初始化为0。
静态局部变量与全局变量共享全局数据区,但静态局部变量只在定义它的函数中可见。
通过声明静态局部变量,但不进行初始化及赋值,那么编译器自动初始化为0,且永远不会改变,所以只会实例化一个对象。这个方法更加便捷高效。
但是上面的代码没有考虑类拷贝的问题,大家参照上面的类拷贝问题可以自己把函数加上,然后去试一试,有问题可以留言大家一起解决~

查看评论

Java 一个对象实例化过程

package day09; class Fu{ Fu(){ super(); show(); return; } void show(){ System.out.printl...
  • china_demon
  • china_demon
  • 2016年01月15日 01:14
  • 2033

Java中创建(实例化)对象的五种方式

Java中创建(实例化)对象的五种方式 1、用new语句创建对象,这是最常见的创建对象的方法。 2、通过工厂方法返回对象,如:String str = String.valueOf(23);  3、...
  • ching_zhi
  • ching_zhi
  • 2016年12月28日 11:13
  • 3133

一个对象的实例化过程【重点】

一、过程  Person p = new Person();  1,JVM会去读取指定路径下的Person.class文件,并加载进内存,    并会先加载Person的父类(如果有直接父类的情况下)...
  • u012986057
  • u012986057
  • 2016年01月23日 16:41
  • 1015

定义一个单例模式的类,在这个类中,只有唯一的实例,不能new出来其他的实例对象。

using System; namespace MySingleton{        class Class1        {                [STAThread]        ...
  • diandian82
  • diandian82
  • 2006年06月15日 18:32
  • 1746

单例模式的几种用法比较

最近在看何红辉、关爱民著的《Android源码设计模式解析与实战》,一边学习,一边理解,一边记笔记。 1.定义 确保某个类只有一个实例,能自行实例化并向整个系统提供这个实例。 2.应用场...
  • luofen521
  • luofen521
  • 2016年06月30日 10:26
  • 6320

你真的会写Java单例么?

java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。   单例模式有一下特点:   1、单例类只能有一个实例。   2、单例类必须自己自己创建自己的唯一实例...
  • Jo__yang
  • Jo__yang
  • 2016年08月04日 20:28
  • 1221

定义一个类让其只能实例化一个对象

一个类只实例化出一个对象称为单例模式
  • Dakuan_chen
  • Dakuan_chen
  • 2017年04月03日 18:42
  • 1057

Java单例设计模式(实现Java的一个类只有一个对象)

单例设计模式的定义:单例设计模式是一种软件设计模式,在它的核心包含一个称为单例类的核心类。核心便是希望一个类只有一个对象。...
  • linux_language
  • linux_language
  • 2016年07月25日 15:22
  • 1386

单例模式的五种写法

首先来明确一个问题,那就是在某些情况下,有些对象,我们只需要一个就可以了,比如,一台计算机上可以连好几个打印机,但是这个计算机上的打印程序只能有一个,这里就可以通过单例模式来避免两个打印作业同时输出到...
  • LM_ZP
  • LM_ZP
  • 2016年05月12日 09:30
  • 6894

设计模式之单例类——如何让一个类只实例化一个对象

这道题的思路是,我只让这个类通过一个公有函数实例化对象,即可以将构造函数设置为私有成员函数。include using namespace std;class Single { public: ...
  • lixungogogo
  • lixungogogo
  • 2016年03月31日 22:17
  • 1527
    个人资料
    等级:
    访问量: 11万+
    积分: 1800
    排名: 2万+
    最新评论