單件模式,像所有的同志一樣我也在用,不過不幸的是我走上了
歧途。鑒于對社會強烈地責任感(吐),我認為有必要做個簡要
的總結來避免后人步我的后塵(狂吐)。
那么現在開始寫正式的悔過書。
首先,首先清一下嗓子,哈哈。
再次,醞釀一下感情。
最后,再清一下嗓子,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。
雙手合十,企求我不是在胡說八道。