在物件導向的程式設計中,類是一種事物的抽象,它並不是實物,故本文其實描述的應該是一個類的物件如何實現自殺;之所以提升到類的高度,是因為實現自殺的函式(方法)是要由類來提供的,而且該類的所有物件都是利用這樣的方法自殺的。

    

為什麼要實現類的自殺?一個類物件要結束自己的生命時,可以直接由建立該物件(例如:new)的主人殺死它(例如:detele)就行了嘛!說的沒錯,大多數情況下的確是這樣的,但凡事總有例外嘛。

 

下面我們首先分析一下一個類物件究竟何時死掉吧!我們把想死的類物件稱為A,另外一個類物件稱為B。

    

【情況1】:

    

A是類B的成員變數。此時B就是A的主人了,主人B在自己死掉(析構)之前會將A殺死,這種情況下A成了B的陪葬品,誰叫B是自己的主子呢!

    

【情況2】:

    

A是在B的某個函式中臨時建立出來的物件。當函式結束後,A的生命就自然終結了,其實是被系統殺死了。此時的A只是這部程式劇本中的一個小小的過客。

    

【情況3】:

    

A是在某個特殊的時候某個地方被B通過new的方法建立的,這時會有一把槍一直指向它。這把對準它的槍可能被B持有,也可能被B轉給了C或者D持有,只要任何人拿槍指向了它,它就得乖乖聽話,聽從指揮。
    

這時,A的生命何時終結完全得看持槍對準它的人的心情了,只要人家一不高興,隨時都可以通過delete把它斃掉。當然,若持槍對準它的人在死的時候都忘記殺死它或者大家的槍都指向了其他地方的話,它便成為了一塊被洩露的記憶體,一直沒有機會死去。

    

【情況4】:

   

A是全域性的靜態物件。這時它的生死不是其他人可以左右的,它有著極長的壽命,隨著整個程式的啟動而誕生,隨著整個程式的結束而死亡。它會在整個程式即將結束前,在其他的非靜態類或者變數都死去之後,與各位靜態物件們一起光榮地被系統殺掉。

   

【情況5】:

    

可能A還有其他的死法,這裡我就不一一列舉了。

       

下面我們切入正題,討論一下類的自殺行為。通過以上幾種情況我們可以看出,物件A的死都不是自願的,都是由系統或者主人強行殺死它的,那麼,究竟什麼情況下會出現A自己想死呢?

    

【情況1】:

    

類A是一個任務執行者,該任務的特點是: 當任務執行完畢後,A必須自殺或者通知上級把自己殺死。

    

例如:A為視訊播放執行者類,當上級建立出A類的物件,並告知A需要播放的資源的必要資訊後,A即啟動對該視訊資源的播放,由於播放是否結束只有底層A才知道,上級是不可能第一時間知道播放已經結束的,這時播放資源該如何正常釋放呢?上級如何才能知道何時把A物件幹掉呢?

這時有兩種途徑:

(1) 由A自行了斷,即自殺,不需要上級再操心,這種情況上級還是挺滿意的,很省事。 

(2) 由A通過某種方式告訴上級:”播放完畢,可以把我幹掉了。” 雖然還得讓上級操心,不過上級處理起來也容器,一刀幹掉A就行了。

    

【情況2】:

    

類A身負國恨家仇,當上級要它死時,它不能立即死掉,而是要繼續完成最後的使命後,再自行了斷。

    

例如:A為某網路傳輸的傳送者,它的任務是將上級交給它的東西傳送到網路接收端B。具體過程是這樣的:上級每次都把需要傳輸給B的東西塞到了A的緩衝區中,A只需不斷地定時從緩衝區取出一定量的資料,然後傳送到B即可。

    

傳輸一段時間後,上級發現需要傳遞到B的東西已經全部塞給A了,於是命令A:“你自殺吧!”;(設定A的自殺變數為true)。這時A發現自己緩衝區的東西還沒有傳輸完畢呢,於是回答上級:“哦,好的,一會我會自殺的”,於是,當A將緩衝區的東西全部傳輸完畢後,便自殺了。
    

這種情況與上面情況1極為相似,但情況還是略有不同的,可能我舉得例子不夠典型,讀者可以自己嘗試建立一個更加典型的例子。

    

【情況3】:
    

類A執行任務的過程中遇到了重大的問題(異常),需要通知上級幹掉自己以保證程式正常執行或者資源的正常釋放。

   

例如:還是舉網路傳送者的例子吧,例如A為某網路傳輸的傳送者,任務依然是向指定目的地址B傳送資料。本來這份工作也挺簡單的,但偏偏老天捉弄人,網路出現了一些問題,導致傳送資料時出現一些異常。這時A敏銳地覺察到了網路的異常情況,這樣繼續傳送資料到B,可能會導致B接收到一些錯誤的資料,很可能發生一些意想不到的異常,因此,A必須停止資料的傳送。這時,A有兩種選擇:(1) 苟且偷生。它大可關閉網路傳送的連線,並且將傳送緩衝區中的資料扔掉,應該能夠保證程式的平安無事,只是上級很是奇怪,為什麼最近B經常告訴自己為什麼沒有發東西過去了?(2)通知上級殺掉自己。A經過仔細權衡,此次異常問題重大,必須立即通知上級幹掉自己,以保證資源的正常釋放,以及後續工作的正常運作。
    

當然,這種情況下的自殺想法一定是發生了重大異常,必須通過幹掉自己才能夠保證後續工作的情況下,A才會產生自殺的想法的。

     

【小結】:
    

我們知道,到達目的地的路徑往往不只一條。上面描述的各種情況其實也都很相似,並且是可以不必使用自殺策略實現最終的目的,比如說:上級開闢一個執行緒,定時不斷地去詢問A的狀態,一旦發現A完成任務了可以死了或者說A遇到異常了想死了,馬上將A殺死即可。我們本文討論的自殺行為只是達到目的的另外一條路徑而已。
    

這裡我們需要注意,我們說的自殺,主要指的是想自殺,實現這樣的想法有兩種途徑,第一種是自己把自己殺死,即“自行了斷”;另外一種是通過通知其他人,達到讓人家把自己殺掉的目的,即“借刀殺己”。
       

    

下面我們將討論一下A到底有哪些辦法實現上面描述的自殺行為?

    

【方法1:傳送訊息】:
    

這種方法有一定的侷限性,它只能用於MFC的框架下,因為MFC實現了訊息機制,我們可以利用該訊息機制將底層的自殺想法傳達到上級,再由上級殺死自己即可。
    

具體用法見MFC的PostMessage和SendMessage兩個函式。
    

本方法屬於“借刀殺己”。

    

【方法2:回撥】:
    

由外界使用者註冊一個回撥函式到本類中,當本類物件想自殺時,可以通過呼叫該回撥函式通知到外界,外界可以在該回撥函式中執行殺死該物件的程式碼。
   

回撥是非MFC下實現通知機制的有效途徑,這種方法其實也屬於“借刀殺己”。

    

【方法3:開執行緒把自己幹掉】:
    

這是一種高階的死法,真正實現了“自行了斷”,不需要外界操心。在類物件產生了“自殺”的想法後,可以立即開啟一個執行緒,將this指標傳遞過去,在該執行緒中執行殺死該類物件的程式碼,終結該物件的生命。
    

使用這種方式需要注意一個問題,那就是外界是不知道你已經死了,所有一定要防止外界在你死後依然使用你,故為了安全起見,自行了斷前或者了斷後還是需要通過某種方式告知一下外界的。

    

【方法4:垃圾回收機制 】:
    

之所以取這個名字,是因為它的確有點像垃圾回收。我們可以專門有一個執行緒,執行緒中會不斷地掃描垃圾回收站(或許是某個靜態單件類)中是否有需要清理的垃圾,若有,則無情地揮舞大刀幹掉這些回收站中的垃圾;於是,當一個類物件想“自殺”時,便通過垃圾回收站提供的介面把自己扔到垃圾回收站中,靜靜地排隊等待被無情地殺死。
    

同樣,這也是一種“自行了斷”的方式,同樣需要注意與【方法3】同樣的問題。

 

好了,現在“一個類如何實現自殺?”這個問題總算討論清楚了,如果大家有什麼意見或者有更好的補充,歡迎留言或者來信交流。