【面试题002】java实现的单例模式,c++实现单例模式,实现禁止拷贝 

一 c++实现单例模式

保证一个类,在一个程序当中只有一个对象,只有一个实例,这个对象要禁止拷贝,注意这里要区别于java。否者的话一个程序当中就可能出现多个对象的拷贝。

我们要禁止拷贝,需要将拷贝构造函数以及等号运算符 声明为私有的,并且呢不提供他们的实现。这样子如果我们代码里面有拷贝构造的话,编译时候会出错。

仅仅这样子是不够的,我们必须将构造函数声明为私有的,这是为了防止外部呢,任意的构造对象。

既然我们将构造函数私有化了,外部就不能通过 Singleton s1; 来定义这样一个对象。那我们就需要提供一个接口让外部呢得到这样一个对象。

Singleton.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 
#include <iostream>
#include <memory>
using namespace std;

class Singleton
{
public:
    /*这个GetInstance是静态的由类直接调用的*/
    static Singleton *GetInstance()
    {

/*用这种方法会出现构造出来的这个对象什么时候释放的问题*/
        /*      if (instacne_ == NULL)
                {
                    instacne_ = new Singleton;
                }
                return instacne_;*/

/* 把裸指针用智能指针来管理
         * 智能指针是重载了点号运算符的,我们访问类本身的get()方法,获得裸指针
         */
        if (!instacne_.get())
        {
            instacne_ = auto_ptr<Singleton>(new Singleton);
        }

return instacne_.get();
    }

~Singleton()
    {
        cout << "~Singleton ..." << endl;
    }
private:
    // 禁止拷贝--构造函数和等号运算符声明为私有的,并且不提供实现。
    Singleton(const Singleton &other);
    Singleton &operator=(const Singleton &other);

// 将构造函数说明为私有的
    Singleton()
    {
        cout << "Singleton ..." << endl;
    }
    /*这实际上是一个静态的类对象,这里仅仅是引用性说明,她的定义应该在类的外边*/
    static auto_ptr<Singleton> instacne_;
};

/*定义性说明*/
auto_ptr<Singleton> Singleton::instacne_;

 
1
2
3
4
5
6
7
8
9
10
11
12
 
int main(void)
{
    //Singleton s1;
    //Singleton s2;

Singleton *s1 = Singleton::GetInstance();
    Singleton *s2 = Singleton::GetInstance();

//Singleton s3(*s1);        // 调用拷贝构造函数

return 0;
}

Makefile:

1
2
3
4
5
6
7
8
9
10
11
12
 
.PHONY:clean  
CPP=g++  
CFLAGS=-Wall -g  
BIN=test  
OBJS=Singleton.o  
LIBS=  
$(BIN):$(OBJS)  
    $(CPP) $(CFLAGS) $^ -o $@ $(LIBS)  
%.o:%.cpp  
    $(CPP) $(CFLAGS) -c $< -o $@  
clean:  
    rm -f *.o $(BIN)  

运行结果

Singleton ...
~Singleton ...

裸指针呢,用智能指针来管理静态的一个类对象,当整个程序结束的时候,静态对象也就被销毁了,

那么静态对象的销毁就会导致这个类对象的析构函数被调用,

instance_.get()

这个get()方法是 智能指针提供的是吧
auto_ptr中有个get方法
还有你给的析构函数  里面并没有释放 那个指针所指的资源 
是程序结束的时候,由智能指针来释放的
智能指针变量 本身不是堆区内存,
智能指针对象销毁的时候,智能指针对象的析构函数会去销毁它所包裹的堆对象

只不过说 智能指针释放了,静态的变量的时候会调用这个变量的析构函数

析构函数是,delete的时候调用的,这个delete操作是在智能指针对象的析构函数中调用的,从而引发了堆对象的析构

如果正常调用析构函数的情况,析构函数你是需要自己是释放对象的资源的,(因为是堆对象,堆上的东西自己释放)
  1. //Singleton s1;
  2. //Singleton s2;
  3. //Singleton s3(*s1);        // 调用拷贝构造函数

这些情况下都是错误的,

运行结果:

g++ -Wall -g -c Singleton.cpp -o Singleton.o
Singleton.cpp: 在函数‘int main()’中:
Singleton.cpp:36:2: 错误: ‘Singleton::Singleton(const Singleton&)’是私有的
Singleton.cpp:59:18: 错误: 在此上下文中
Singleton.cpp:57:13: 警告: 未使用的变量‘s2’ [-Wunused-variable]
make: *** [Singleton.o] 错误 1

二,实现禁止拷贝

Nocopyable这个类如何保证禁止拷贝,她的实现和Singleton类的实现差不多。

Noncopyable.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 
#include <iostream>
#include <memory>
using namespace std;

class Noncopyable
{
protected:
    Noncopyable() {}
    ~Noncopyable() {}
private:
    Noncopyable(const Noncopyable &);
    const Noncopyable &operator=(const Noncopyable &);
};

class Parent : private Noncopyable
{
public:
    Parent()
    {

}
    Parent(const Parent &other) : Noncopyable(other)
    {

}
};

class Child : public Parent
{
public:
    //Child(const Child& other)
    //{

//}
};

int main()
{
    /*这两种情况都是失败的*/
    //Parent p1;
    //Parent p2(p1);
    // 要调用Parent拷贝构造函数,
    //Parent构造函数又调用Noncopyable的拷贝构造函数

Child c1;
    Child c2(c1);
    return 0;
}

注意:

private 是实现继承,并不是为了继承她的接口

public 是接口继承

Makefile:

1
2
3
4
5
6
7
8
9
10
11
12
 
.PHONY:clean  
CPP=g++  
CFLAGS=-Wall -g  
BIN=test  
OBJS=Noncopyable.o  
LIBS=  
$(BIN):$(OBJS)  
    $(CPP) $(CFLAGS) $^ -o $@ $(LIBS)  
%.o:%.cpp  
    $(CPP) $(CFLAGS) -c $< -o $@  
clean:  
    rm -f *.o $(BIN)  
运行结果:
 
1
2
3
4
5
 
g++ -Wall -g -c Noncopyable.cpp -o Noncopyable.o
Noncopyable.cpp: 在复制构造函数‘Parent::Parent(const Parent&)’:
Noncopyable.cpp:11:2: 错误: ‘Noncopyable::Noncopyable(const Noncopyable&)’是私有的
Noncopyable.cpp:23:49: 错误: 在此上下文中
make: *** [Noncopyable.o] 错误 1

这里我们需要注意的地方是,

对于构造函数来说,如果基类有默认构造函数,即使我们没有写 :Noncopyable()这句话,他也是会自动调用基类的默认构造函数的,

但是拷贝构造函数就不一样啦,如果我们没有写 :Noncopyable(other)这句话,是不会调用基类的拷贝构造函数的,

当然如果基类没有默认的构造函数,那么这个时候呢,一定要在成员列表中给出对基类构造函数的调用。

JAVA实现的单例模式:

读取配置文件,并且实例化了一个对象,这个对象保证只有一个。

 Java Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
package com.ebupt.ebms.conf;

/**
 * @author zling Create on 2011-3-7
 * @version 1.0
 */
public class MainConfig
{
    private String logPath = ""; // 上传的各种日志的本地路径

private static MainConfig instance = new MainConfig();//懒人模式

public static MainConfig getInstance()
    {
        if (instance == null)
            instance = new MainConfig();
        return instance;
    }

public String string()
    {

StringBuffer sb = new StringBuffer();
        sb.append("logPath : ").append(logPath).append("\n");
        return sb.toString();
    }

public String getLogPath()
    {
        return logPath;
    }

public void setLogPath(String logPath)
    {
        this.logPath = logPath;
    }

}

【面试题002】java实现的单例模式,c++实现单例模式,实现禁止拷贝的更多相关文章

  1. 1、c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

    1.c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

  2. 面试题_ Java EE 相关的面试题

    为了做 Java EE 的朋友,这里列出了一些 web 开发的特定问题,你们可以用来准备 JEE 部分的面试: 10 大 Spring 框架面试题及答案(参见)10 个非常好的 XML 面试问题(Ja ...

  3. Java设计模式之(一)------单例模式

    1.什么是单例模式? 采取一定的办法保证在整个软件系统中,单例模式确保对于某个类只能存在一个实例.有如下三个特点: ①.单例类只能有一个实例 ②.单例类必须自己创建自己的实例 ③.单例类必须提供外界获 ...

  4. Java 设计模式系列(一)单例模式

    Java 设计模式系列(一)单例模式 保证一个类只有一个实例,并且提供一个访可该实例的全局访问点. 一.懒汉式单例 /** * 懒汉式单例类:在第一次调用的时候实例化自己 * 1. 构造器私有化,避免 ...

  5. 【笔试题】Java笔试题知识点

    Java高概率笔试题知识点 Java语法基础部分 [解析]java命令程序执行字节码文件是,不能跟文件的后缀名! 1.包的名字都应该是由小写单词组成,它们全都是小写字母,即便中间的单词亦是如此 2.类 ...

  6. 面试题-关于Java线程池一篇文章就够了

    在Java面试中,线程池相关知识,虽不能说是必问提,但出现的频次也是非常高的.同时又鉴于公众号"程序新视界"的读者后台留言让写一篇关于Java线程池的文章,于是就有本篇内容,本篇将 ...

  7. 【单例模式】单例模式 & GCD单例模式 & 将封装单例模式到宏

    懒汉式单例模式 下面的代码块, 基本是单例模式的完整版本了. 可扩展的地方,可以在init方法中作扩展. // static 在全局变量的作用域仅限于当前文件内部 static id _instanc ...

  8. 关于Java的Object.clone()方法与对象的深浅拷贝

    文章同步更新在个人博客:关于Java的Object.clone()方法与对象的深浅拷贝 引言 在某些场景中,我们需要获取到一个对象的拷贝用于某些处理.这时候就可以用到Java中的Object.clon ...

  9. java面试题002

    1.判断下列代码的运行情况 public class TestExtends { public static void main(String[] args) { Father obj = new S ...

随机推荐

  1. 8款效果惊艳的HTML5 3D动画

    1.HTML5 WebGL水面水波荡漾特效 之前已经向各位分享过一款很逼真的HTML5水波荡漾特效,效果还算不错.今天再向大家分享一款更加给力的HTML5水波动画,画面上是一个大水池,水池底部是一颗大 ...

  2. C++ 11 之Lambda

    1.Lambda表达式来源于函数式编程,说白就了就是在使用的地方定义函数,有的语言叫“闭包”,如果 lambda 函数没有传回值(例如 void ),其回返类型可被完全忽略. 定义在与 lambda ...

  3. 【风马一族_xml】xml的两种解析思想

    xml的解析思想 dom解析 将整个xml使用类似树的结构保存在内存中,再进行对其操作 是woc组织推荐的处理xml的一种方式 需要等到xml完全加载进内存才可以进行操作 耗费内存.当解析超大的xml ...

  4. 增量与位置PID

    转载:http://blog.sina.com.cn/s/blog_408540af0100b17n.html http://bbs.ednchina.com/BLOG_ARTICLE_211739. ...

  5. gprof

    函数级耗时剖析.gprof不会说谎,仔细考虑下函数的实现细节. 准备工作 对单文件simulator.cpp编译 编译:g++ -g -pg simulator.cpp -o simulator.o ...

  6. ADO.NET笔记——带参数的查询防止SQL注入攻击

    相关知识: 把单引号替换成两个单引号,虽然能起到一定的防止SQL注入攻击的作用,但是更为有效的办法是把要拼接的内容做成“参数” SQLCommand支持带参数的查询,也就是说,可以在查询语句中指定参数 ...

  7. c#获取今天星期几

    System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.GetDayName(DateTime.Now.DayOfWeek)

  8. 生成动态前缀且自增号码的Oracle函数

    create or replace Function GetInvitationNO(prev varchar2, num1 varchar2, num2 varchar2, sessionSetti ...

  9. 【linux】iptables 开启80端口

    经常使用CentOS的朋友,可能会遇到和我一样的问题.开启了防火墙导致80端口无法访问,刚开始学习centos的朋友可以参考下. 经常使用CentOS的朋友,可能会遇到和我一样的问题.最近在Linux ...

  10. VC Dimension -衡量模型与样本的复杂度

    (1)定义VC Dimension: dichotomies数量的上限是成长函数,成长函数的上限是边界函数: 所以VC Bound可以改写成: 下面我们定义VC Dimension: 对于某个备选函数 ...