我正在查看 CodeGear C Builder 頭檔案的源代碼。在Source/vcl/forms.pas我找到以下代碼行:
procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
Instance: TComponent;
begin
Instance := TComponent(InstanceClass.NewInstance); // ????? ????, ?????
TComponent(Reference) := Instance;
try
Instance.Create(Self); // ? ??
except
TComponent(Reference) := nil;
raise;
end;
if (FMainForm = nil) and (Instance is TForm) then
begin
TForm(Instance).HandleNeeded; // ?????? ??
FMainForm := TForm(Instance);
end;
end;
從背景關系來看,我認為正在發生的是這個程序創建了一個型別的實體InstanceClass并通過Reference. 在我的電話中,InstanceClassis not TForm,所以后半部分無關緊要。
我很困惑TComponent(Reference) := Instance;。從語法上講,這里發生了什么?這是通過參考分配的嗎?這是分配一個新TComponent的實體化器引數Reference被分配的值嗎?是TComponent()型別轉換嗎?
uj5u.com熱心網友回復:
- 在
procedure's 簽名中,形參reference并不表示資料型別,而是被宣告為variable 引數。 - 無型別引數在 Pascal 中是不合法的,但在GNU Pascal和 FreePascal 等方言中是允許的。在那里,這些可變引數接受任何資料型別的實際引數。編譯器不會強制/限制允許的資料型別,但它必須是可尋址的(即不允許使用文字)。
dataTypeName(expression)確實是一種型別轉換(在 Pascal 中也是非法的,但在某些方言中是允許的)。具體來說,dataTypeName(variableName)是一個變數 typecast。它將被視為具有variableName指定資料型別。這是必要的,因為在這種特殊情況下reference沒有關聯的資料型別。沒有關聯的資料型別意味著,在如何訪問有問題的變數方面沒有商定的規則(即任何讀/寫訪問都是不可能的)。- 該程序可能會創建
TComponentClassi 的實體。e. 引數的資料型別InstanceClass,但是您應該真正閱讀該NewInstance方法的檔案。我只能告訴你它是一個后代,TComponent否則將型別轉換為不相關的類幾乎沒有意義。
uj5u.com熱心網友回復:
該Reference引數是無型別var引數。在 C 術語中,它大致相當于void*,即任何變數的地址都可以系結到它。代碼將型別轉換Reference為等價于TComponent*&或TComponent**,然后將Instance變數(TComponent*指標)分配給呼叫者傳遞的變數。
代碼大致等價于 C 中的以下代碼(除了元類和虛擬建構式在 C 中不存在,因此這段代碼實際上在 C 中不可用):
void __fastcall TApplication::CreateForm(TComponentClass* InstanceClass, void* Reference)
{
// this just allocates a block of memory of the required size...
TComponent* Instance = static_cast<TComponent*>(InstanceClass->NewInstance());
// *static_cast<TComponent**>(Reference) = Instance;
reinterpret_cast<TComponent*&>(Reference) = Instance;
try
{
// This is calling the class' virtual constructor
// on the allocated memory. In C , this would be
// similar to calling 'placement-new' if the class
// type was known statically here...
// new(Instance) InstanceClass->ClassType()(this);
Instance->Create(this);
}
catch (...)
{
// *static_cast<TComponent**>(Reference) = NULL;
reinterpret_cast<TComponent*&>(Reference) = NULL;
throw;
}
if ((!FMainForm) && (dynamic_cast<TForm*>(Instance) != NULL))
{
static_cast<TForm*>(Instance)->HandleNeeded();
FMainForm = static_cast<TForm*>(Instance);
}
}
// Application.CreateForm(TForm, Form1);
Application->CreateForm(__classid(TForm), reinterpret_cast<void*>(&Form1));
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/433768.html
上一篇:可以按名稱更新TRecord成員
