【面试题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. 【WinForm】线程中向listview添加数据

    在使用listview的时候,因为处理的数据较多,为防止在处理数据时出现假死的状态出现卡的情况,我们使用委托进行处理添加数据 定义委托 private delegate void AddListVie ...

  2. Mysql 正则获取字段的交集【转】

    问题描述 比如table1中有两条记录 name no a    2,9 b    8,10 然后有一串字符串,是0,1,2,3,4 然后通过一条sql,找出no为2,9的记录来``` 因为字符串中有 ...

  3. oracle-11g创建用户名的时候默认区分大小写

    oracle11g-11.2.0.3.0 - 64bit oracle-11g创建用户名的时候默认区分大小写 设置不区分大小写: alter system set sec_case_sensitive ...

  4. SSH时不需输入密码

      我这里有2台机器,一台装了Teradata数据库,ip是192.168.184.128,称它为teradata-pc:另一台装了Oracle数据库,ip地址是192.168.184.129,称它为 ...

  5. hornetq 入门(1)

    Hornetq 版本2.4.0final  需要JDK7及以上 Hornetq官网 Hornetq2.1中文手册 step1.启动服务端 1.1准备配置文件(配置说明参考官网手册) hornetq-c ...

  6. ListIterator-迭代器

    Iterable(lang)-->Iterator(util)-->ListIterator(util) method: 1.void add(E o) 2.boolean hasNext ...

  7. 【原创】jQuery插件 - Booklet翻书特效教程(一) 一般设置

    jQuery插件 - Booklet翻书特效教程(一) 一般设置 本文由五月雨恋提供,转载请注明出处. 一.宽高(width/height) 1.自定义大小 $(function(){ // 自定义页 ...

  8. Underscore 源码

    Underscore 源码 作者:韩子迟 What? 不知不觉间,「Underscore 源码解读系列」进入了真正的尾声,也请允许我最后一次 po 下项目的原始地址 https://github.co ...

  9. JPA学习---第八节:使用JPQL语句进行查询

    1.JPQL 语句查询,代码如下: @Test public void query(){ EntityManagerFactory factory = Persistence.createEntity ...

  10. 阿里云服务器上安装mysql的心路历程(博友们进来看看哦)

    在阿里云花了100买了一台云服务器,配置如下: CPU: 1核 内存: 512MB 数据盘: 0G 带宽: 1Mbps 阿里云服务器安装mysql搞得我想吐血,搞了一个多星期,现在才搞好,而且,还有许 ...