【面试题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. javascript笔记——label包含的自定义按钮选中

    自定义按钮ui样式就是需要有label包含input以及带另外的标签作为新ui的载体,此时触发label的click的时候也会选中按钮,也就是说存在事件捕获,解决这个问题有如下方式 用到了 mouse ...

  2. 分布式MySQL 数据库

    http://zhangxugg-163-com.iteye.com/blog/1666673 而本文所描述的 federated属于 MySQL的一种特殊引擎,利用它可将本地数据表映射至远程 MyS ...

  3. curl raise 信号出core

    在使用c++多线程使用libcurl抓取网页时,遇到程序随机core掉的情况,gdb 一下出错信息有这么一条:longjmp causes uninitialized stack frame. 在网上 ...

  4. linux系统man查询命令等级与意义

    代号 意义 1 可执行程序和一般shell命令 2 系统调用函数 3 库函数 4 设备配置文件,通常在/dev下 5 配置文件,/ec下 6 游戏 7 协议及杂项 8 管理员命令 9 与内核相关

  5. Source Insight建工程之Kernel

     不管你是从事于Linux内核工作还是出于兴趣爱好,Linux内核源码都是非常好的学习资源.意味着就要经常的和内核源码大交道,那么软件工具就是少不了的.在Windows系统上确实有着许多好用的软件 ...

  6. lnmp下配置虚拟主机

    一:首先熟悉几个命令 which php      --->  which是通过 PATH环境变量到该路径内查找可执行文件,所以基本的功能是寻找可执行文件 whereis php   ----& ...

  7. php出现“syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM”错误的一种情况,及解决方法

    PHP中的“syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM”错误,可能是因为美元符号$的误用,看下面一种情况 class Test{         s ...

  8. android 线程

    android线程: 通用多个线程通信管理框架: 1.Handler监听者框架:子线程是事件源,主线程是监听者.        Handler作为子线程的监听器出现:主线程中生成Handler的子类, ...

  9. Oracle中的if...then...elsif

    if...then...elsif实现多分支判断语句 其语法如下: if <condition_expression1> then plsql_sentence_1; elseif< ...

  10. Basic Operation about Linux

    1. 永久开启/关闭防火墙 在linux中防火墙是一个名叫iptables的工具 开启: chkconfig iptables on 关闭: chkconfig iptables off 即时生效,重 ...