Дестру́ктор — специальный метод класса, служащий для деинициализации объекта (например освобождения памяти).
Синтаксис деструктора
C++: имя деструктора совпадает с именем класса, перед которым стоит символ тильда (~). См. пример ниже. D: деструкторы имеют имя ~this(). Rust: деструкторы построены на типаже Drop. Delphi: деструкторы имеют ключевое слово destructor и могут иметь любое имя, но обычно именуется как Destroy. Object Pascal: деструкторы имеют ключевое слово destructor и могут иметь любое имя, но обычно именуется как Destroy. Objective-C: деструкторы имеют имя dealloc. Perl: деструкторы имеют имя DESTROY; в расширении Moose для Perl 5, деструкторы имеют название DEMOLISH. PHP: В PHP 5+, деструкторы имеют имя __destruct. В более ранних версиях PHP деструкторов не было.Деструкторы , в онлайн документации по PHP Python: есть методы с именем __del__, называемые деструкторами в руководстве по языку Python 2, но на самом деле они являются финализаторами, как это объявлено в Python 3. Swift: деструкторы имеют имя deinit.
Деструктор в Delphi
Для объявления деструктора в Delphi используется ключевое слово destructor. Имя деструктора может быть любым, но рекомендуется всегда называть деструктор Destroy.
TClassWithDestructor = class destructor Destroy; override; end;
В Delphi все классы являются потомками, по крайней мере, класса TObject, поэтому, для корректного освобождения памяти, необходимо перекрывать деструктор, используя директиву override.
В Delphi прямой вызов деструктора используется редко. Вместо него используют метод Free.
MyObject.Free;
Метод Free вначале проверяет существует ли уничтожаемый объект, а затем вызывает деструктор. Этот прием позволяет избегать ошибок, возникающих при обращении к несуществующему объекту.
Деструктор в C++
#include <iostream> using namespace std;
class NameOfClass
private: int a; public: NameOfClass(int m); ~NameOfClass();
NameOfClass::~NameOfClass()
cout << this->a << endl;
NameOfClass::NameOfClass(int m)
a = m;
~NameOfClass() — деструктор, имеет имя ~NameOfClass, не имеет входных параметров.
В данном случае при уничтожении объекта выводит в консоль параметр a.
Деструктор в Python В Python поддерживаются деструкторы и для них есть ключевое слово del, но, в отличие от delete в C++, del только уменьшает счетчик ссылок на объект и не обязательно немедленно уничтожает объект.
class Destructible: def __init__(self, name: str) -> None: self.name: str = name print(f"Created Destructible: {self.name}")
def __del__(self) -> None: print(f"Destructor called for: {self.name}")
if __name__ == "__main__": d: Destructible = Destructible("My name") print(f"Using Destructible: {d.name}") del d
Подобно Java и C#, в Python есть блок try-with-resources, называемый блоком with или «контекстным менеджером». Он используется для таких вещей, как файлы и сетевые соединения.
from typing import Optional
class Destructible: def __init__(self, name: str) -> None: self.name: str = name
def __enter__(self) -> "Destructible": print(f"Entering context (allocating resource: {self.name})") return self
def __exit__(self, exc_type: Optional[type], exc_val: Optional[Exception], exc_tb: Optional[type]) -> None: print(f"Exiting context (cleaning up resource: {self.name})")
if __name__ == "__main__": with Destructible("Resource A") as d: print(f"Using resource {d.name} inside context")
# Most Python standard library resources support with blocks: with open(file_path, "r") as file: print("Reading the file content:") content: str = file.read() print(content)
Деструктор в Rust struct Foo { i: i32, }
impl Foo { fn new(i: i32) -> Foo { Foo { i }
impl Drop for Foo { fn drop(&mut self) { println!("{}", self.i);
}В блоке impl для структуры Foo реализуется одноимённый метод типажа Drop. В коде ниже создаётся переменная foo. Благодаря умной модели памяти, деструктор будет вызван автоматически и без накладных расходов, как только закончится область видимости переменной.let foo = Foo::new(42);
Виртуальный деструктор
Деструктор интерфейсов или абстрактных классов обычно делают виртуальным. Такой прием позволяет корректно удалять без утечек памяти, имея лишь указатель на базовый класс.
Пусть (на C++) есть тип Father и порождённый от него тип Son:
class Father { public: Father() {} ~Father() {}
class Son : public Father { public: int* buffer; Son() : Father() { buffer = new int; } ~Son() { delete[] buffer; }
Нижеприведённый код является некорректным и приводит к утечке памяти.
Father* object = new Son(); // вызывается Son() delete object; // вызывается ~Father()!!
Однако, если сделать деструктор Father виртуальным:
class Father { public: Father() {} virtual ~Father() {}
class Son : public Father { private: int* buffer; public: Son() : Father() { buffer = new int; } ~Son() { delete[] buffer; }
вызов delete object; приведет к последовательному вызову деструкторов ~Son и ~Father.
Ссылки
См. также Класс (программирование) Конструктор Финализатор Блок инициализации
Категория:Метод (информатика) Категория:Статьи с примерами кода на Паскале Категория:Статьи с примерами кода C++