今天乙個好友在群裡問:
: 在vcl庫里,大多數建構函式是virtual的,這是為啥
: 按理,在呼叫建構函式之前,物件都還沒有,
: 當然也應該沒有vtbl,那麼這樣virtual有什麼意義呢?
: 所以c++裡的建構函式沒有virtual的。
: 難道delphi裡不是醬紫地?
: 那麼vtbl是在什麼時候被初始化的?
首先,為什麼沒有呼叫建構函式之前,呼叫virtual函式沒有意義,而呼叫實函式就有意義呢?因為虛方法和實方法不同,呼叫實方法的時候,實際上是呼叫類的方法,在例項沒有建立前,就可以呼叫的。而虛方法不同,虛方法依賴於例項,必須要例項的vmt表建立後才能呼叫。
那麼回到主題,為什麼vcl裡很多建構函式是虛函式呢?
因為vcl的初始化實際上都是在newinstance裡完成的。
create只是把最後的堆記憶體,變成可用的指標
在delphi源**裡,可以看到:
class function tobject.newinstance: tobject;
begin
result := initinstance(_getmem(instancesize));
end;
class function tobject.initinstance(instance: pointer): tobject;
varintftable: pinte***cetable;
classptr: tclass;
i: integer;
begin
fillchar(instance^, instancesize, 0);
pinteger(instance)^ := integer(self);
classptr := self;
while classptr <> nil do
begin
intftable := classptr.getinte***cetable;
if intftable <> nil then
for i := 0 to intftable.entrycount-1 do
with intftable.entries[i] do
begin
if vtable <> nil then
pinteger(@pchar(instance)[ioffset])^ := integer(vtable);
end;
classptr := classptr.classparent;
end;
result := instance;
end;
可以看出,最終的構造是在newinstance裡完成。
後記:本來問題到這裡就結束了,誰知道哪天看書,發現原來newinstance也是虛函式。$%#^$%^$#@!!那是怎麼回事呢?原來是自己想多了,***.create呼叫的是類的方法,而在delphi裡,類在程序啟動的時候已經初始化了,虛擬表也存在,所以。。。。。。
建構函式為什麼不可以為虛函式
1,從儲存空間角度 虛函式對應乙個vtable,這大家都知道,可是這個vtable其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,無法找到vtable,所以建構函式不能是虛函式。2,從使用角度 虛函式主要用...
建構函式可以為虛函式嗎?
答案當然是否定的,主要從一下兩個角度加以說明。從儲存空間角度 虛函式對應乙個vtable,可是這個vtable其實是儲存在物件的記憶體空間的。那麼問題來了,如果建構函式是虛函式,就要通過vtable來呼叫,可是物件空間還沒有例項化,也就是記憶體空間還沒有,無法找到vtable,所以建構函式不能是虛函...
析構函式為何可以為虛函式?
首先要明確 1.每個析構函式 不加 virtual 只負責清除自己的成員。2.可能有基類指標,指向的確是派生類成員的情況。這是很正常的 那麼當析構乙個指向派生類成員的基類指標時,程式就不知道怎麼辦了。所以要保證執行適當的析構函式,基類中的析構函式必須為虛析構。基類指標可以指向派生類的物件 多型性 如...