//singleton.h
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include "synobj.h"
template<typename T>
class Singleton
{
public:
static T* Instance();
protected:
private:
Singleton();
~Singleton();
Singleton(Singleton& );
Singleton& operator = (Singleton& );
static void Destory();
private:
static T* _instance;
static Mutex _mutex;
};
//singleton.cpp
//volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.
#include "stdafx.h"
#include "singleton.h"
#include <iostream>
#include <stdlib.h>
using namespace std;
template<typename T> T* Singleton<T>::_instance = NULL;
template<typename T> Mutex Singleton<T>::_mutex;
template<typename T>
Singleton<T>::Singleton()
{
}
template<typename T>
Singleton<T>::~Singleton()
{
}
template<typename T>
T* Singleton<T>::Instance()
{
if(_instance == NULL )
{
Lock lock(_mutex);
if(_instance == NULL)
{
T* temp = new T;
_instance = temp;
//_instance = new T();
atexit(Destory);
}
}
return _instance;
}
template<typename T>
void Singleton<T>::Destory()
{
if(NULL != _instance)
{
delete _instance;
_instance = NULL;
}
}
// Singleton20.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "singleton.h"
#include "synobj.h"
#include <stdio.h>
#include <iostream>
using namespace std;
class A:public Singleton<A>
{
public:
void DoSomething()
{
cout<<"hello DoSomething"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = A::Instance();
a->DoSomething();
getchar();
return 0;
}
我的代码大致是这样的,各位前辈们,帮忙分析一下我的错误吧。。。。
用模板类的实现应该写在.h里面,最好是将.h命名成.hpp,你看看boost里面的头文件基本都是.hpp
这个其实是因为模板在编译的时候并没有实例化,看下这个文章吧c++模板类(一)理解编译器的编译模板过程
vs应该不支持模版分离,你把模版定义,实现都放在一起。
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&id=4281275&uid=26611383
http://www.cnblogs.com/08shiyan/archive/2012/03/16/2399617.html
http://blog.csdn.net/scutth/article/details/7997685
将声明和定义都放在一起后,发现还是有一个小小的问题,不知道为什么?请大家帮忙再看一下吧
//singleton.h
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include "synobj.h"
#include <stdlib.h>
template<typename T>
class Singleton
{
public:
static T* Instance()
{
if(NULL == _instance)
{
Lock lock(_mutex);
if(NULL == _instance)
{
T* temp = new T;
_instance = temp;
atexit(Destory);
}
}
return _instance;
}
protected:
private:
Singleton(){}
~Singleton(){}
Singleton(Singleton& ){}
Singleton& operator = (Singleton& ){}
static void Destory()
{
if(NULL != _instance)
{
delete _instance;
_instance = NULL;
}
}
private:
static T* _instance;
static Mutex _mutex;
};
template<typename T> T* Singleton<T>::_instance = NULL;
template<typename T> Mutex Singleton<T>::_mutex;
// Singleton20.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "singleton.h"
#include "synobj.h"
#include <stdio.h>
#include <iostream>
using namespace std;
class A:public Singleton<A>
{
public:
void DoSomething()
{
cout<<"hello DoSomething"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = A::Instance();
a->DoSomething();
getchar();
return 0;
}
将类模板的构造函数和析构函数的声明和定义放在public下面,就可以测试通过了,可是这是为什么呢?
你用的什么编译器版本,VC6? 请用最新的编译器VS2012等。老版本编译器有问题。
然后就是析构函数最好用虚函数
virtual ~Singleton(){};
谢谢各位前辈们的热心解答
下面我把代码贴出来
//singleton.h
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include "synobj.h"
#include <stdlib.h>
template<typename T>
class Singleton
{
public:
static T* Instance()
{
if(NULL == _instance)
{
Lock lock(_mutex);
if(NULL == _instance)
{
T* temp = new T;
_instance = temp;
//_instance = new T();
atexit(Destory);
}
}
return _instance;
}
protected:
Singleton(){}
~Singleton(){}
private:
Singleton(Singleton& );
Singleton& operator = (Singleton& );
static void Destory()
{
if(NULL != _instance)
{
delete _instance;
_instance = NULL;
}
}
private:
static T* _instance;
static Mutex _mutex;
};
template<typename T> T* Singleton<T>::_instance = NULL;
template<typename T> Mutex Singleton<T>::_mutex;
#include "stdafx.h"
#include "singleton.h"
#include "synobj.h"
#include <stdio.h>
#include <iostream>
using namespace std;
class A:public Singleton<A>
{
friend Singleton<A>;
public:
void DoSomething()
{
cout<<"hello DoSomething"<<endl;
}
protected:
A(){}
~A(){}
};
int _tmain(int argc, _TCHAR* argv[])
{
A* a = A::Instance();
a->DoSomething();
A* b =A::Instance();
b->DoSomething();
//A* c = new A();
//c->DoSomething();
if(a == b)
{
cout<<"Singleton Success"<<endl;
}
else
{
cout<<"Singleton Fail"<<endl;
}
getchar();
return 0;
}
以前只是对别人用模板,觉得没有什么太大难度,真正自己写的时候发现漏洞百出啊,要认真向大家学习啊。。。。
为什么要把类模板中的构造函数声明为protected?
程序员在使用模板类时最常犯的错误是将模板类视为某种数据类型。所谓类型参量化(parameterized types)这样的术语导致了这种误解。模板当然不是数据类型,模板就是模板,恰如其名:
编译器使用模板,通过更换模板参数来创建数据类型。这个过程就是模板实例化(Instantiation)。
从模板类创建得到的类型称之为特例(specialization)。
因为classA:public template<A>{},这里要用到继承,所以我们类模板中的构造函数不能私有,必须声明为public或者protected
在类A中,我们为了维护类A实例的唯一型,所以我们要将其构造函数声明为protected或者private,这样的话在模板类中Instance中的T* temp = new T;这一句将报错,为什么呢?因为类A中构造函数为protected,我们可以在类A中将template<T>声明为friend,即friend template<A>,这样问题就解决了,代码详见楼上。。。。。