2012-05-25 2 views
4

Учитывая следующий Delphi код, Foo является Free «D на FormClose, но TFoo.Destroy не вызывается - и поэтому Bar не Free» d, что приводит к утечке памяти?Почему Destroy не называется?

Пропустил ли я что-то здесь или не должен Foo.Free.Free.Foo.Destroy в какой-то момент?

type 
    TBar = class 
    SomeInteger : integer; 
end; 

TFoo = class 
    Bar : TBar; 

    constructor Create(); 
    destructor Destroy(); 
end; 

var 
    Foo : TFoo; 

implementation 

constructor TFoo.Create; 
begin 
    Bar := TBar.Create; 
    Bar.SomeInteger := 2; 
end; 

destructor TFoo.Destroy; 
begin 
    Bar.Free; 
    Bar := nil; 

    showmessage('Destroyed!'); 
end; 

procedure TForm10.FormCreate(Sender: TObject); 
begin 
    Foo := TFoo.Create; 

    showmessage('Foo created'); 
end; 

procedure TForm10.FormDestroy(Sender: TObject); 
begin 
    Foo.Free; 
    Foo := nil; 
end; 
+0

деструктор Destroy(); *** override; *** К сожалению. –

+3

Разве компилятор не предупредил вас о вашем коде? Это должно быть. Что-то о скрытии виртуального метода с тем же именем. –

+0

Никогда не игнорируйте предупреждение. Игнорировать предупреждение игнорирует ошибку, во многих случаях! –

ответ

18

Вы должны пометить подпись деструктора с переопределением.

destructor Destroy(); override; 

И вы должны иметь inherited в конце деструктора. Но поскольку ваш класс не получен ни от чего, кроме TObject, я подозреваю, что это не имеет значения.

+0

Кажется, мы справились с этим в одно и то же время ... Ответ будет принят, когда мне будет позволено! Я думал, что попробовал переопределить, но я тоже переопределил Create, и это дает ошибку компиляции. –

+0

Справа, Стив. 'Override' идет с виртуальными методами. 'TObject.Create' не является виртуальным, поэтому вы не можете его переопределить. 'TObject.Destroy' * является * виртуальным. –

8

Уничтожить виртуально, и поэтому вы должны переопределить его в своем классе потомков.

TFoo = class 
    Bar : TBar; 

    constructor Create(); 
    destructor Destroy(); override; // must add override here 
end; 

Без переопределения деструктор никогда не вызывается, а вместо него используется базовый класс.

+3

Спасибо, попал туда в конце. Как всегда, он был частью гораздо более крупного проекта и не мог понять, что происходит. Как ни странно, упрощение проблемы сделало проблему ... проще. –

Смежные вопросы