【面试题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 /*用这种方法会出现构造出来的这个对象什么时候释放的问题*/ /* 把裸指针用智能指针来管理 return instacne_.get(); ~Singleton() // 将构造函数说明为私有的 /*定义性说明*/ |
1
2 3 4 5 6 7 8 9 10 11 12 |
int main(void)
{ //Singleton s1; //Singleton s2; Singleton *s1 = 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 ...
裸指针呢,用智能指针来管理静态的一个类对象,当整个程序结束的时候,静态对象也就被销毁了,
那么静态对象的销毁就会导致这个类对象的析构函数被调用,
只不过说 智能指针释放了,静态的变量的时候会调用这个变量的析构函数
- //Singleton s1;
- //Singleton s2;
- //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 class Parent : private Noncopyable } } class Child : public Parent //} int main() Child c1; |
注意:
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实现的单例模式:
读取配置文件,并且实例化了一个对象,这个对象保证只有一个。
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;
/** private static MainConfig instance = new MainConfig();//懒人模式 public static MainConfig getInstance() public String string() StringBuffer sb = new StringBuffer(); public String getLogPath() public void setLogPath(String logPath) } |