2011-08-04 8 views
3

静的なクラスメソッドと通常のルーチンポインタは実用的な観点から互換性がありますが、コンパイラはこれを知らないようです。例:コメント、3aに述べたように静的クラスメソッドと通常のルーチンポインタはどのように互換性がありますか?

type 
    TFunc = function(i: Integer): string; 

    TMyClass = class 
    public 
    class function StaticMethod(i: Integer): string; static; 
    end; 

class function TMyClass.StaticMethod(i: Integer): string; 
begin 
    Result := '>' + IntToStr(i) + '<'; 
end; 

function GlobalFunc(i: Integer): string; 
begin 
    Result := '{' + IntToStr(i) + '}'; 
end; 

procedure CallIt(func: TFunc); 
begin 
    Writeln(func(42)); 
end; 

begin 
    CallIt(TMyClass.StaticMethod); //  1a: doesn't compile 
    CallIt(GlobalFunc); //     1b: compiles 

    CallIt(@TMyClass.StaticMethod); //  2a: compiles iff $TYPEDADDRESS OFF 
    CallIt(@GlobalFunc); //     2b: compiles iff $TYPEDADDRESS OFF 

    CallIt(Addr(TMyClass.StaticMethod)); // 3a: compiles 
    CallIt(Addr(GlobalFunc)); //   3b: compiles 

    Readln; 
end. 

及び3bは両方コンパイル(をコンパイルこの単純な例で実行時に作品を含みます)。 2aおよび2bは、$TYPEDADDRESSOFFの場合にのみコンパイルされます。しかし、1a/1bは異なります。1bは常にコンパイルしますが、1aはコンパイルしません。これは設計上の区別ですか? 3aを使用していますか、落とし穴を見落としましたか?

+1

'CallIt(@ TMyClass.StaticMethod);'はうまく動作します。 – kludg

+0

言及を忘れた:私は '$ TYPEDADDRESS ON'を使用する。 –

+1

@Ulrich - Sergは既に 'Addr()'が{$ T +}に対して免疫されておらず、 '@'はそうでないという答えを出しました。これは[ドキュメント](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/System_Addr.html)です。 –

答えて

7

静的なクラス関数と通常の関数の間のバイナリレベルには違いはありません。&結果型 - バイナリと互換性があります。もちろん、それらはコンパイラの種類が異なるため、例をコンパイルするにはAddr()または@が必要です。

{$T+} 
begin 
    CallIt(@TMyClass.StaticMethod); 
    Readln; 
end. 

[パスカルエラー] Project10.dpr(:

Addr()は、あなたがあなたの例に型チェックを切り替えるdirective.Ifの$ Tコンパイラがコンパイルされませんで、それが影響を受けないことを除いて@オペレータに相当します28):E2010互換性のないタイプ: 'TFunc'と 'Pointer'

+0

Re *異なるタイプのコンパイラ*:それがポイントです - なぜ彼らは少なくとも割り当てに互換性がありませんか? C++グローバルルーチンと静的メソッドのAFAIRは互換性があります。 –

+0

@Ulrich - これはコンパイラデザイナーの選択です。私はコンパイラ設計者が伝統的なパスカルの "強力な型付け"の制限を取り除くだけで、その言語に新しい機能を追加することが本当に必要であると思います。 – kludg

関連する問題