一 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 ...
裸指针呢,用智能指针来管理静态的一个类对象,当整个程序结束的时候,静态对象也就被销毁了,
那么静态对象的销毁就会导致这个类对象的析构函数被调用,
这个get()方法是 智能指针提供的是吧
auto_ptr中有个get方法
还有你给的析构函数 里面并没有释放 那个指针所指的资源
是程序结束的时候,由智能指针来释放的
智能指针变量 本身不是堆区内存,
只不过说 智能指针释放了,静态的变量的时候会调用这个变量的析构函数
//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; } }