VB中到底有沒有構造函數和析構函數?答案是肯定的!
之前在網上搜索了一些相關內容,發現,很多關於VB構造函數的提問都被回覆為“vb中沒有構造函數”,這一不包含任何模糊性副詞的肯定句。而一旦涉及到構造函數,話題就會被立即偷換為VB.NET或java和C++。之前在百度上搜索"vb 構造函數"得到的也都是與VB.NET相關的搜索結果。所以,這就是我要發表本經驗的原因,希望本經驗能幫到越來越多的人!同時,我也想奉勸那些在網上回答問題的人,在回答問題之前一定要“三思而後行”,如果對vb的瞭解不夠深入就最好不要輕易下定論誤導別人。
工具/原料
顯然是VB6,VB7以上的版本就直接用.NET好了、
方法與詳解
首先要有一個類,也就是類模塊,使用VB類生成器或全部自己寫代碼均可,在此不詳敘,網上關於此的技術文章還是很多的。
簡單理解一下構造函數和析構函數。構造函數和析構函數從邏輯上講是咱們寫代碼給系統用的,咱們自己沒有場合去手動調用這樣的函數,即使是能手動調用那一般也沒這麼幹的,因為它是一個用來初始化對象(收拾殘局)的函數,所以它會在對象建立後(銷燬前)馬上被調用,不容時間去讓我們手動調用。
若用VB的思維去考慮剛才的那個問題,那麼就有點像是在對象被建立時觸發了這個對象中一個事件,就像Private Sub Form_Load()一樣,在對象建立後,就會自動跳轉到這裡執行裡面的代碼。好,理解到這裡,我就可以告訴大家了,VB中類的構造函數和析構函數分別是
Sub Class_Initialize()
End Sub
和
Sub Class_Terminate()
End Sub
可以自己親自打代碼在類模塊中添加這兩個過程,也可以真的就像是在窗體裡添加事件一樣,直接在左上角寫著"(通用)"的下拉框裡選擇"Class",然後就在右邊的下拉框裡VB其實就已經為我們準備考了Initialize和Terminate兩個過程的聲明。
就像第二步裡說的一樣,不希望我們去手動調用這兩個過程,所以這兩個過程一般被聲明為Private,這樣在類外就找不到這兩個方法了。如果是用的第二種方法創建的這兩個過程,VB直接就會把它們聲明為Private。
Private Sub Class_Initialize()
……
End Sub
和
Private Sub Class_Terminate()
……
End Sub
到此,大家可能會有個問題,就是這個構造過程可不可以帶上參數呢?這個我會很遺憾地告訴大家,是不能的,VB沒有給我們提供對編寫帶參數的構造過程的支持。若嘗試以下代碼:
Private Sub Class_Initialize(Optional ByVal a As Integer = 0)
……
End Sub
編譯就會報錯,說“過程聲明與同名事件或過程的描述不匹配”。當然,VB也不支持這種寫法:
Set a As New MyClass(5)
拓1:VB對象的處理方式
假設自己寫的類名叫MyClass
1.所有定義為對象類型的變量,均為空殼,並無真正的對象,類似於C++中的對象指針:
Dim a As MyClass
這樣,就有了一個MyClass類型的空殼,表示這個變量a可以裝載一個MyClass類型的對象,以及將來a能執行的方法。它為4個字節,存儲的是對象的首地址。定義為對象類型的變量,初值均為Nothing,類似於C++中的一個對象指針變量指向NULL。
2.在VB中,對象只能動態創建,通過使用New關鍵字。這句代碼和C++就有點相似了。
Dim a As MyClass
Set a = New MyClass
這兩句代碼才真正的使a帶上內容。
3.“Set a = ……”這樣的代碼實際上就相當於C++中讓指針指向某個對象的操作。省略號的地方可以是一個New出來的新對象,也可以是之前的一個已有的同類型的對象,也可以是Nothing,即讓它再指向空,變回空殼:
Dim a As MyClass
Dim b As MyClass
Set a = New MyClass
Set b = a
Set a = Nothing
與數值類型和字符串變量不一樣的是,對象變量在條件表達式中判斷相等可不是還用=等號,而是用關鍵字Is
If a Is Nothing Then
'如果a是一個空殼
End If
4.Object類型的變量:
Dim a As Object
Object類型就像是VB中所有類的大基類一樣,此時a這個空殼裡可以裝任何類型的對象,也可以通過a調用a裡裝的對象的屬性方法等。這樣說來,VB還帶有一點支持“動態聯編”的感覺。
拓2:對象構造和析構的時機
如果理解了拓1的內容,自然就會理解,VB觸發構造過程的時機為使用New關鍵字的時候。
Dim a As MyClass
Set a = New MyClass '執行到這句時就會調用構造過程
VB對象觸發析構過程的時機是在這個對象沒有被任何殼子裝著的時候,也就是沒有任何指針指向它的時候,它就會被析構。下面舉3個例子:
Private Sub Command1_Click()
Dim a As MyClass
Set a = New MyClass '觸發構造過程
Set a = Nothing '此時由於沒有任何殼子裝著原來a裡的對象了,所以這句會觸發析構過程
End Sub
Private Sub Command2_Click()
Dim a As MyClass
Set a = New MyClass '觸發構造過程
End Sub 'a的生存期至此結束,也相當於沒有任何殼子裝著原來a裡的對象了,所以這句會觸發析構過程
Private Sub Command3_Click()
Dim a As MyClass
Dim b As MyClass
Set a = New MyClass '觸發構造過程
Set b = a '理解為兩個指針指向同一個對象
Set a = Nothing '此時因為還有b仍在裝著這個對象,所以它不會被析構
Set b = Nothing '這時才會觸發析構
End Sub
注意事項
VB中沒有複製構造函數,因為沒有場合。從拓1的內容可以看出,如果函數參數中傳的是對象,那麼它一定為地址傳遞,不需要將原對象複製一份到參數中。另一方面,VB不支持帶參數的構造過程,這也決定著VB不會有複製構造函數,因為我們因此也無法在新建對象時指定新對象的模樣。