2015-01-06 31 views
2

與問題相關TVirtualMethodInterceptor.Create doesn't support the class that has overload virtual method.。在修改RRUZ的答案後,我又遇到了另一個問題。 我應該如何調用第二種重載方法「SaveLog(str:string; Args:TConst數組)」;「 。 如以下代碼RTTI&Variant Open Array Parameters

type 

    TConst = array of TVarRec; 

    TLog = class 
    public 
    constructor Create(); 

    procedure SaveLog(str: string); overload; virtual; 
    procedure SaveLog(str: string; Args: TConst); overload; virtual; 
    end; 

constructor TLog.Create(str: string); 
begin 

end; 

procedure TLog.SaveLog(str: string); 
begin 
    MessageBox(GetFocus(), PChar(str), 'Test Message', MB_OK); 
end; 

procedure TLog.SaveLog(str: string; Args: TConst); 
var 
    buf: string; 

begin 
    buf:=Format(str, Args); 
    SaveLog(buf); 
end; 


procedure MyTest(nID: Integer); 
var 
    ttt: TLog; 
    vmi: TVirtualMethodInterceptor; 

begin 
    ttt:=TLog.Create(); 
    try 
    ttt.SaveLog('ID = %d', [nID]); 
    vmi:=TVirtualMethodInterceptor.Create(ttt.ClassType); 
    try 
     // 
    finally 
     vmi.Free(); 
    end; 
    finally 
    ttt.Free(); 
    end; 
end; 

代碼 「ttt.SaveLog( 'ID =%d',[的NID]);」 將得到 編譯器錯誤:E2250有 'SaveLog',可以是無重載版本用這些論據調用。 我該怎麼辦?

回答

1

Args參數是一個動態數組。創建並填充一個動態數組並通過它。

您的代碼無法編譯,因爲您嘗試傳遞開放數組構造函數。如果你有一個開放的數組,那麼這將是有效的,但你沒有。你有一個動態數組。

您可能會用到的一個有用技巧是定義一個函數,該函數接受一個變體開放數組並返回一個動態數組。然後你可以使其中一個適應另一個。該函數定義應該像這樣:

function VariantOpenArrayToDynArray(const Args: array of const): TArray<TVarRec>; 

請注意,我更喜歡使用通用的動態數組TArray<T>而不是你的TConst的。這樣做有更好的類型兼容性。

Rudy Velthuis詳細介紹了這一點,並展示瞭如何在本文中實現適配器功能:Open array parameters and array of const


也就是說,TVarRec不是爲明確使用而設計的。它是變體開放數組的運行時支持。正如Rudy的文章所表明的那樣,一旦你留下了編譯器支持變體開放數組的安全範圍,就需要一些顯式的內存管理。我不會推薦使用TArray<TVarRec>

取而代之的是,我建議您使用現代變體類型,這種類型是專門爲新款RTTI設計的。那是TValue。這種變體類型是專爲明確使用而設計的,內存管理是自動執行的。使用TArray<TValue>而不是TArray<TVarRec>

+3

@AndersenChang:另外,請閱讀:[打開數組參數和常量數組](http://rvelthuis.de/articles/articles-openarr.html)以瞭解您的「TConst」類型與打開陣列。它們是相關的,但不相同。 –

+0

這是來自@Rudy的一個很好的鏈接,它展示瞭如何實現聲明我給出的函數 –

+0

@Andersen它比在TVarRec中沒有存儲值的數據類型更復雜。見魯迪的文章。 –