现在的位置: 首页 > 综合 > 正文

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

2013年07月30日 ⁄ 综合 ⁄ 共 9162字 ⁄ 字号 评论关闭

一 c++实现单例模式

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

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

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

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

Singleton.cpp:

#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_;

int main(void)
{
	//Singleton s1;
	//Singleton s2;

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

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

	return 0;
}

Makefile:

.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操作是在智能指针对象的析构函数中调用的,从而引发了堆对象的析构

如果正常调用析构函数的情况,析构函数你是需要自己是释放对象的资源的,(因为是堆对象,堆上的东西自己释放)

	//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:

#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:

.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)

运行结果:

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实现的单例模式:

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

package com.ebupt.ebms.conf;

/**
 * @author zling Create on 2011-3-7
 * @version 1.0
 */
public class MainConfig {

	private boolean useCache = true;// 是否缓存

	private boolean videoConvert = false;// 是否进行视频格式转换
	
	private boolean useMail = true;//是否进行邮件通知

	private Integer sessionTimeOut = 3 * 60 * 1000;

	private String logPath = ""; // 上传的各种日志的本地路径

	private String webPath = ""; // 播放任务描述文件基路径,播放列表和资源清单均在该基路径下

	private String urlPath = ""; // 终端访问基路径,可为http或ftp的基路径

	private String tomcatPath = ""; // Tomcat 服务器所在路径

	private String phoneNumber = "";// 维护人员手机号码,多个之间用逗号分隔
	
	private String email = "";// 维护人员邮箱地址,多个之间用逗号分隔

	private String mailServer = "";// 邮箱服务器地址

	private String mailAccount = "";// 邮箱账号

	private String mailPasswd = "";// 邮箱密码
	
	private String ltpasso = "";// 北京移动基于LTPA方式的SSO
	
	private String sitesso = "";// 北京移动基于SiteMinder方式的SSO
	
	private String ssourl = "";// SSO的服务路径
	
	private String fouraurl = "";// 4A账号操作相关的rul
	private String fouracheckurl = "";// 4A校验相关的url
	
	private String redirecturl = "";// 验证成功后跳转到的路径
	
	private String localfourapath = "";// 本地存放生成的4a日志文件的路径
	private String fouraftpurl = "";// 4aftp的url
	private String fouraftpport = "";// 4aftp的port
	private String fouraftpname = "";// 4aftp的username
	private String fouraftppwd = "";// 4aftp的password
	private String fouraftpsavepath = "";// 4aftp保存文件的路径
	private String fouraftpfilename = "";// 4a要求的上传到ftp服务器的日志文件的名称


	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");
		sb.append("webPath : ").append(webPath).append("\n");
		sb.append("urlPath : ").append(urlPath).append("\n");
		sb.append("tomcatPath : ").append(tomcatPath).append("\n");
		sb.append("useCache : ").append(useCache).append("\n");
		sb.append("useMail : ").append(useMail).append("\n");
		sb.append("videoConvert : ").append(videoConvert).append("\n");
		sb.append("sessionTimeOut : ").append(sessionTimeOut).append("\n");
		sb.append("phoneNumber : ").append(phoneNumber).append("\n");
		sb.append("email : ").append(email).append("\n");
		sb.append("mailServer : ").append(mailServer).append("\n");
		sb.append("mailAccount : ").append(mailAccount).append("\n");
		sb.append("mailPasswd : ").append(mailPasswd).append("\n");
		sb.append("ltpasso : ").append(ltpasso).append("\n");
		sb.append("sitesso : ").append(sitesso).append("\n");
		sb.append("ssourl : ").append(ssourl).append("\n");
		sb.append("fouraurl : ").append(fouraurl).append("\n");
		sb.append("fouracheckurl : ").append(fouracheckurl).append("\n");
		sb.append("redirecturl : ").append(redirecturl).append("\n");
		sb.append("localfourapath : ").append(localfourapath).append("\n");
		sb.append("fouraftpurl : ").append(fouraftpurl).append("\n");
		sb.append("fouraftpport : ").append(fouraftpport).append("\n");
		sb.append("fouraftpname : ").append(fouraftpname).append("\n");
		sb.append("fouraftppwd : ").append(fouraftppwd).append("\n");
		sb.append("fouraftpsavepath : ").append(fouraftpsavepath).append("\n");
		sb.append("fouraftpfilename : ").append(fouraftpfilename).append("\n");
		return sb.toString();
	}

	public boolean isUseCache() {
		return useCache;
	}

	public void setUseCache(boolean useCache) {
		this.useCache = useCache;
	}

	public boolean isUseMail() {
		return useMail;
	}

	public void setUseMail(boolean useMail) {
		this.useMail = useMail;
	}

	public boolean isVideoConvert() {
		return videoConvert;
	}

	public void setVideoConvert(boolean videoConvert) {
		this.videoConvert = videoConvert;
	}

	public Integer getSessionTimeOut() {
		return sessionTimeOut;
	}

	public void setSessionTimeOut(Integer sessionTimeOut) {
		this.sessionTimeOut = sessionTimeOut;
	}

	public String getLogPath() {
		return logPath;
	}

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

	public String getWebPath() {
		return webPath;
	}

	public void setWebPath(String webPath) {
		this.webPath = webPath;
	}

	public String getUrlPath() {
		return urlPath;
	}

	public void setUrlPath(String urlPath) {
		this.urlPath = urlPath;
	}

	public String getTomcatPath() {
		return tomcatPath;
	}

	public void setTomcatPath(String tomcatPath) {
		this.tomcatPath = tomcatPath;
	}

	public String getPhoneNumber() {
		return phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	public String getMailServer() {
		return mailServer;
	}

	public void setMailServer(String mailServer) {
		this.mailServer = mailServer;
	}

	public String getMailAccount() {
		return mailAccount;
	}

	public void setMailAccount(String mailAccount) {
		this.mailAccount = mailAccount;
	}

	public String getMailPasswd() {
		return mailPasswd;
	}

	public void setMailPasswd(String mailPasswd) {
		this.mailPasswd = mailPasswd;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getLtpasso() {
		return ltpasso;
	}

	public void setLtpasso(String ltpasso) {
		this.ltpasso = ltpasso;
	}

	public String getSitesso() {
		return sitesso;
	}

	public void setSitesso(String sitesso) {
		this.sitesso = sitesso;
	}

	public String getSsourl() {
		return ssourl;
	}

	public void setSsourl(String ssourl) {
		this.ssourl = ssourl;
	}
	
	public String getFouraurl() {
		return fouraurl;
	}

	public void setFouraurl(String fouraurl) {
		this.fouraurl = fouraurl;
	}

	public String getRedirecturl() {
		return redirecturl;
	}

	public void setRedirecturl(String redirecturl) {
		this.redirecturl = redirecturl;
	}

	public String getLocalfourapath() {
		return localfourapath;
	}

	public void setLocalfourapath(String localfourapath) {
		this.localfourapath = localfourapath;
	}

	public String getFouraftpurl() {
		return fouraftpurl;
	}

	public void setFouraftpurl(String fouraftpurl) {
		this.fouraftpurl = fouraftpurl;
	}

	public String getFouraftpport() {
		return fouraftpport;
	}

	public void setFouraftpport(String fouraftpport) {
		this.fouraftpport = fouraftpport;
	}

	public String getFouraftpname() {
		return fouraftpname;
	}

	public void setFouraftpname(String fouraftpname) {
		this.fouraftpname = fouraftpname;
	}

	public String getFouraftppwd() {
		return fouraftppwd;
	}

	public void setFouraftppwd(String fouraftppwd) {
		this.fouraftppwd = fouraftppwd;
	}

	public String getFouraftpfilename() {
		return fouraftpfilename;
	}

	public void setFouraftpfilename(String fouraftpfilename) {
		this.fouraftpfilename = fouraftpfilename;
	}

	public String getFouraftpsavepath() {
		return fouraftpsavepath;
	}

	public void setFouraftpsavepath(String fouraftpsavepath) {
		this.fouraftpsavepath = fouraftpsavepath;
	}

	public String getFouracheckurl() {
		return fouracheckurl;
	}

	public void setFouracheckurl(String fouracheckurl) {
		this.fouracheckurl = fouracheckurl;
	}
	
	
}

抱歉!评论已关闭.