2012-04-21 8 views
11

Próbuję zrozumieć przekazać przez wartość i przekazać przez odniesienie w VB6. Rozumiem te pojęcia w pełni w językach programowania zorientowanego obiektowo, takich jak .NET i Java (zdaję sobie sprawę, że Java nie ma przejścia przez odniesienie). Spójrz na poniższy kod:VB6 przejść przez wartość i przejść przez odniesienie

Private Sub Form_Load() 

Dim Test As Integer 
Test = 1 
TestFunction Test 'line 5 
MsgBox (Test) 

End Sub 

Private Sub TestFunction(ByVal i As Integer) 
    i = i + 1 
End Sub 

Okno komunikatu wyświetla 1 zgodnie z oczekiwaniami. Jeśli wstawię nawiasy klamrowe do Testu w wierszu 5, to okno komunikatu wypisze 1, jak można się spodziewać. Teraz spójrz na poniższy kod:

Private Sub Form_Load() 

Dim Test As Integer 
Test = 1 
TestFunction Test 'line 5 
MsgBox Test 

End Sub 

Private Sub TestFunction(ByRef i As Integer) 
    i = i + 1 
End Sub 

Okno komunikatu drukuje 2, jak można się spodziewać. Jeśli jednak dodasz nawiasy do wiersza 5, to okno komunikatu wypisze 1, czego bym się nie spodziewał. Wygląda na to, że funkcja wywołująca może przejść przez wartość, nawet jeśli zmienną zdefiniowaną w wywołanej funkcji jest ByRef. Wydaje się, że tak nie jest, np. Jeśli wywoływana funkcja ma sygnaturę ze zmienną zdefiniowaną jako ByVal, to zawsze będzie ona ByVal (nawet jeśli nie ma nawiasów wokół zmiennej w funkcji wywołującej). Jakie jest to myślenie w VB6? Zdaję sobie sprawę, że jest to podstawowe pytanie w VB6, ale mnie zdezorientowało. Przeczytałem dokumentację MSDN i zdaję sobie sprawę, że to wszystko prawda, ale nie wyjaśnia to myślenia, które za tym stoi.

Odpowiedz

16

To klasyczna karta w VB6. Jest to explained in the VB6 manual. W tym kodzie poniżej VB6 traktuje argumentu jako ekspresji (Test) niż sygnał sterujący

TestFunction (Test) 

w celu przekazania odniesienie do zmiennej pomiń wsporniki lub używanie starszej Call statement (co wymaga wsporniki)

TestFunction Test 
Call TestFunction(Test) 

VB6 pozwala na przepuszczanie wyrażeń ByRef argumentów, nawet jeśli metoda zmienia je. Np. Można napisać:

TestFunction (Test + 2) 

Kompilator tworzy tymczasową kopię i przekazuje ją przez odwołanie. VB.Net uses brackets in a similar way.

Można również uzyskać kompilator stworzyć tymczasowe kopie jeśli TestFunction przyjmuje dwa argumenty tak:

TestFunction (one), (two) 

I można dostać tymczasowe kopie nawet z Call jeśli podwoi swoje nawiasy, dodając dodatkowy unecessary parę:

Call TestFunction((Test)) 
+0

Dzięki. Jest to przydatne. Jaki jest cel funkcji Call? Czy to oznacza, że ​​przekazana zmienna nigdy nie będzie traktowana jako wyrażenie? Jestem tym zaskoczony, ponieważ nigdy tak naprawdę nie myślałem o tym wcześniej. Ponadto, jeśli istnieje więcej niż jedna zmienna do przekazania, to zakładam, że nie można dołączyć wyrażenia? – w0051977

+2

Nie jestem pewien, jak to jest "gotcha", ponieważ jest udokumentowane, zamierzone zachowanie. Słowo kluczowe Call jest starsze i przestarzałe, wracając do wczesnych podstaw MS. To było, aby ułatwić przenoszenie starych programów do przodu. – Bob77

+2

Słowo kluczowe "Call" nie ma żadnego znaczenia, niezależnie od tego, czy argumenty są traktowane jak wyrażenia. Po prostu używa nawiasów jako sposobu przekazywania argumentów, więc jedna para nawiasów ma inne znaczenie. Ale nawiasy wokół argumentu dają wyrażenie tak samo, jak bez słowa kluczowego "Call". –

6

Enclosing dowolne wyrażenie w nawiasach powoduje, że ekspresja zostać ocenione zanim cokolwiek innego, nawet gdy wyrażenie jest tylko jedna zmienna. W twoim przypadku wynik tego wyrażenia jest następnie przekazywany jako argument.

Tak więc, w rzeczywistości przekazujesz argument przez odniesienie. Ale argument, który przechodzisz, jest wynikiem wyrażenia, a nie oryginalnej zmiennej. Dlatego oryginalna zmienna nie jest aktualizowana.