单件模式,像所有的同志一样我也在用,不过不幸的是我走上了
歧途。鉴于对社会强烈地责任感(吐),我认为有必要做个简要
的总结来避免后人步我的后尘(狂吐)。
那么现在开始写正式的悔过书。
首先,首先清一下嗓子,哈哈。
再次,酝酿一下感情。
最后,再清一下嗓子,OK,THATS ALL,^_^.
所有有正义感的人都在向我扔鼠标,有的人开始搬起显示器。好
,好,在这种躁动下,不利于我诚心接受犯下的滔天错误,请大
家少安毋躁,请看下下面的代码:
template <typename T> class Singleton
{
protected:
T* ms_Singleton;//此行黏贴错误,前面应该加 STATIC
public:
Singleton( void )
{
assert( !ms_Singleton );
ms_Singleton = static_cast<T*>(this);
}
~Singleton( void )
{ assert( ms_Singleton ); ms_Singleton = 0; }
static T& getSingleton( void )
{ assert( ms_Singleton ); return (
*ms_Singleton ); }
static T* getSingletonPtr( void )
{ return ( ms_Singleton ); }
};
非常明显,这段代码是无懈可击的,嘿嘿。出品人( Paul D
Turner)。
那么看看我糟糕的表现:
class Application: public Singleton<Application>
{
public:
static Application* getSingletonPtr();
static Application getSingletonP();
void Run();
}
明眼人一眼就看出了端倪,我犯了个超级错误,那就是
Application getSingletonPtr();
这是致命的缺陷,直接导致了单件模式的失败,这样的写法首先
语法上是说的过去的,但事实上我并没有重载
Application& getSingleton();所以当我在别的类中用
Application::getSingleton()时出现了让我眼前发黑的一暮。
因为当程序刚刚跳出调用这个方法的方法时(like that:
void ClassRoot::RunApplication
{
Application::getSingleton().Run();
}
)
,Application的析构函数被调用,结果可想而知,Application
中的所有的资源都被释放。接着系统无情的扔出一个面目可憎的
窗体,对我进行了最为严厉的批评,这个批评直接导致了你在此
消磨时间。特别声名,由此对你青春的耽搁,从刑法上讲,我不
会负主要责任,^_^.
“这是为什么”,我问了同样的问题而且不只“千百遍”。我只
是没有用引用而已,是的,引用,这的确是个问题。就象用指针
一样,引用也是没有问题地。前面程序失败的原因是有新的临时
Application实例产生,当运行完RunApplication时,临时对象
被释放,他调用了析构函数,不幸的是,我在他里面释放了一些
指针和资源,错误产生了,他是如此的自然和顺理成章。
引用,指针,我想有必要看看他们的猫腻所在。
LOOK一下下面的代码:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
class ouyang2008
{
public:
int a;
int b;
ouyang2008(){a=0;b=0;}
~ouyang2008(){}
void printtext()
{
//cout<<a<<endl<<b<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ouyang2008* pObj=new ouyang2008;
//cout<<pObj<<endl;
ouyang2008& obj=*pObj;
ouyang2008* p=&obj;
delete pObj;
cout<<p;
return 0;
}
现在我们注意的焦点在:
ouyang2008& obj=*pObj;
ouyang2008* p=&obj;
看看他们有什么不同,那么我们怎么LOOK呢?WIN32 ASM,
yes,it is that:
ouyang2008& obj=*pObj;
00411556 mov eax,dword ptr [ebp-14h]
00411559 mov dword ptr [ebp-20h],eax
ouyang2008* p=&obj;
0041155C mov eax,dword ptr [ebp-20h]
0041155F mov dword ptr [ebp-2Ch],eax
哦,ALL is here ,so it is org.
从汇编上来看,他们没有任何区别,他们都在函数的堆栈中保存
了一个对象的指针,所以当退出函数时只是释放了指针而已,对
对象没有任何影响。
现在我们可以讲:
对机器来说他们没有任何区别。
对使用者来讲,咳、咳、咳,我不得不很无奈的重复别人所说的
“引用是安全的”。
为什么是安全的?
第一,你不用担心释放的问题。
第二呢,你不会很惊讶地看着让你胆战心惊的“EXCEPTION
ASSETT ERROR ox0000005 access invalidate”.
运行以下下面的代码:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
class ouyang2008
{
public:
int* a;
int* b;
ouyang2008(){a=new int[1];b= new int[1];}
~ouyang2008(){delete[] a;delete[] b;a=b=NULL;}
void printtext()
{
cout<<*a<<endl<<*b<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ouyang2008* pObj=new ouyang2008;
//cout<<pObj<<endl;
ouyang2008& obj=*pObj;
ouyang2008* p=&obj;
delete pObj;
if (p)//祸根
{
p->printtext();
}
cout<<p;
return 0;
}
当然如果你现在的工作是对付。NET
你没有必要注意这方面的问题:
曾经有为老兄在。NET还到处是臭虫的时候就这样说过:
“对于。NET来讲,任何类的对象都是在堆中建立的,类的变量
和对象之间只有引用,如果你在栈中看到了类的对象,那你就是
见到鬼了,而且是。NET鬼。”
呵呵,THAT IS OVER。
双手合十,企求我不是在胡说八道。