2012-02-28 41 views
2

下面的項目無法運行「訪問衝突」錯誤。我使用Delphi XE2更新3.Delphi編譯器錯誤還是我的錯?

program Project1; 

{$APPTYPE CONSOLE} 

type 
    TTestClass = class 
    public 
    class procedure Test; 
    end; 

var 
    TestClass: TTestClass; 

class procedure TTestClass.Test; 
begin 
end; 

begin 
    TestClass.Test; 
end. 

如果我標誌着作爲class procedure Test 「靜態」,是沒有問題的。這是'設計'嗎?

P.S .:這是我的錯誤,對我感到羞恥。

+5

「對你感到羞恥」?也許。但至少你足夠謙虛,認爲這可能是你的錯誤,而不是編譯器錯誤,並詢問比你更瞭解的人。恭喜你;這是一位優秀工程師的標誌之一。 – 2012-02-28 17:15:41

回答

7

是的,你目睹的是正確的。

非靜態類方法,就像實例方法一樣,有一個隱藏的Self參數。對於類方法,這指的是類參考。這就像編譯器將你的方法到這一點:

type 
    TTestClassClass = class of TTestClass; 

procedure TTestClass_Test(Self: TTestClassClass); 

當你調用一個類的方法在非類接收器(即對象引用),編譯器插入到ClassType呼叫填寫該參數與在運行時類型的對象,像這樣:

TTestClass_Test(TestClass.ClassType); 

ClassType方法獲取該對象的VMT的地址,但你的變量不涉及任何VMT。您的變量可能是空指針或未初始化的,因此如果您幸運的話,試圖將其解引用到讀取VMT地址會導致訪問衝突。 (如果你不走運,它將取消對地址的引用,並且地址恰好位於程序地址空間的其他地方,並且結果被解釋爲VMT指針,即使它不是。)

調用類引用的類方法或僅限有效的對象引用。

TTestClass.Test; 

當你把它在一個類引用「文字」如上述,編譯器已經知道第一個參數的值和轉換這樣的呼籲:

TTestClass_Test(TTestClass); 
1

您正在調用一個無參考的方法。即使類方法使用它們被調用的對象來確定運行時變量的實際類型。你所要做的

TestClass := TTestClass.Create; 

實際創建類的實例,然後

FreeAndNil(TestClass); 

釋放它。

如果你

TTestClass.Test; 

接着,電話是在編譯時解決,因爲它不依賴於變量的類型,所以它的工作原理。

+0

我真的需要創建一個類的實例來訪問'類過程'嗎? – BofA 2012-02-28 16:37:35

+0

-1如果你需要創建一個類的實例來調用它,那麼作爲一個類過程有什麼意義呢? – ComputerSaysNo 2012-02-28 16:40:20

+0

實際上,我的不好,沒有讀完整個代碼,他宣佈了一個變量類型... – ComputerSaysNo 2012-02-28 16:43:10

0

問題是,雖然你有TTestClass的聲明變量,但你沒有實例化。在cn使用Test方法之前,您需要調用Create,否則它將失敗(除了您的靜態,它不需要實例化整個類)。所以你的主要代碼是

begin 
    TestClass := TTestClass.Create; 
    TestClass.Test; 
    TestClass.Free; 
end. 
0

以下作品完美在XE中,它似乎是你的Delphi版本中的一個錯誤,只要它不在類中調用一個不是實例的「私有」變量,那麼你的代碼是正確的,但我認爲你已經明白了。

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils; 

type 
    TTest = class 
    public 
    class procedure test; 
    end; 

{ TTest } 

class procedure TTest.test; 
begin 
    Writeln('hello'); 
end; 

begin 
    try 
    TTest.test; 
    Readln; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 
+0

OP沒有使用'TTest.test'他使用單元化變量'TestClass.Test'調用Test meththod – RRUZ 2012-02-28 16:48:33

+0

這適用於所有的Delphi版本,但它與問題中的代碼不同。 – 2012-02-28 16:48:54

+0

@RRUz,大衛是的,我已經閱讀他的代碼在「急」,並作出了不好的回答......我已經意識到後,已經爲時已晚...... – ComputerSaysNo 2012-02-28 17:07:40

2

聽起來很合理。 TestClass是零。您無法在非實例上調用非靜態類方法:

'可以通過類引用或對象引用來調用類方法。當通過對象引用調用它時,對象的類將變爲自我的值 - 無對象,無類。

'類的靜態方法可以在沒有對象引用的情況下訪問' - 由於對類方法的直接靜態調用,對TestClass實例無關緊要。