Tentang alokasi dan daur ulang memori objek
Saya tidak tahu apakah ada yang punya ide untuk memasang daftar dl di sini. Jika tidak, pikirkan saja. Padahal sebelum kode berikut (1), ada baris kode MOV dl, 1, jadi kenapa seperti ini? Mengenai kegunaan register dl disini ada pengantarnya di bantuan Delphi. Sabar dan cari sendiri. Kalau ketemu pasti jadi masternya. Ini belajar, bukan, belajar memancing, bukan meminta ikan. Borland mengatakan ini, "Saya menggunakan register dl untuk menyimpan sebuah bendera. Jika nilainya 1, maka saya akan membuat objek. Jika tidak, saya tidak akan membuat objek tersebut." Jika Anda sedikit kabur, pikirkan lagi dan lagi. Kalau belum buka mata coba lihat kode berikut (2), jangan bilang belum ketemu uhuk, ada apa, saya ngomong omong kosong terus, saya berjanji tidak akan mengatakannya. lagi.
{Kode (1)
tes dl, dl
jz+$08
tambahkan esp, -$10
hubungi @ClassCreate }
{///Kode (2)
Prosedur Tapplication.CreateForm(InstanceClass: TComponentClass; Referensi var);
var
Contoh: TComponent;
mulai
//////// Instance := TComponent(InstanceClass.NewInstance);
TComponent(Referensi) := Instance;
mencoba
//////// Instance.Create(Self);
kecuali
TComponent(Referensi) := nihil;
mengangkat;
akhir;
jika (FMainForm = nil) dan (Instance adalah TForm) maka
mulai
TForm(Instance).HandleNeeded;
FMainForm := TForm(Instance);
akhir;
akhir;
}
Dalam hal ini, Delphi memanggil kode (1) ketika instance dari kelas yang dibuat dipanggil untuk pertama kalinya. Lalu, jika ada yang perlu memanggil metode Create, saya, bukan, itu kompilernya saja seperti ini MOV dl, 0, sehingga instruksi lompat judgement 0 pada kode (1) akan menuju ke tempat yang seharusnya. (Mengapa kamu berbicara omong kosong lagi? Terakhir kali, saya janji.) Sebenarnya, metode Buat di sini hanyalah sebuah metode biasa, dan , Anda juga harus memperhatikan bahwa panggilan pertama ke metode Create atau metode NewInstance adalah kelas yang mengirimkan pesan ini (perhatikan bahwa pesan ini bukan Pesan Windows, pesan ini bukan pesan yang lain, haha, itu omong kosong lagi, ini benar-benar yang terakhir kali, benar. Jika Anda tidak memahami pesan di sini, silakan pelajari pengetahuan berorientasi objek dan pemodelan dengan cermat) dan telepon nanti. Metode Create adalah objek yang sudah mapan, Instance.Create(Self); pikirkanlah, tentu saja nilai register dl telah berubah.
Oke, saya tidak punya banyak waktu. Terakhir, saya ingin menambahkan tentang bendera (metode terjemahan Taiwan, menurut saya kata ini bagus, saya sarankan Anda juga menggunakannya untuk menyelamatkan saya dari banyak masalah nanti) dan petunjuk penggunaan register dl ini, harus dikatakan Tidak akan ada perubahan apa pun.Kalau dipikir-pikir baik-baik, Delphi tidak berubah dari 1 menjadi 6. Ngomong-ngomong, itu juga membuktikan bahwa desainer HB Delphi adalah seorang desainer. karakter. Tentu saja, saya tidak bisa membandingkannya. Haha, ini dia lagi, oke, aku berhenti bicara. Oh, terakhir, izinkan saya mengatakan bahwa metode TObject.Create bukanlah metode kosong, ingat, lalu pikirkanlah.
Oke, hal-hal lain, silakan pergi dan lihat sendiri. Kalau begitu, Anda akan mendapat banyak keuntungan.
“Keluar dari sini, aku ingin melihat dan memikirkannya, dan aku tidak ingin omong kosongmu!” :)
selamat tinggal
Ketika kompiler mengalokasikan memori untuk suatu objek, dukungan yang diberikannya adalah dengan memasukkan baris kode perakitan berikut sebelum memanggil konstruktor:
tes dl, dl
jz+$08
tambahkan esp, -$10
call @ClassCreate // Perhatikan baris kode ini
Baris terakhir dari kode di atas memanggil fungsi _ClassCreate pada baris 8949 dari file system.pas (tergantung pada Delphi 6). Setelah alokasi memori selesai, konstruktor kelas dipanggil untuk menginisialisasi anggota data. Setelah itu, compiler akan memasukkan baris kode assembly berikut:
tes dl, dl
jz +$0f
hubungi @AfterConstruction
pop dWord ptr fs:[$00000000]
tambahkan esp, $0c
Tugas utamanya adalah memanggil AfterConstruction dari setiap instance objek. Panggilan ini tidak ada gunanya di Delphi.
Demikian pula, ketika menghancurkan suatu objek, destruktor kelas harus dipanggil terlebih dahulu untuk melepaskan sumber daya yang diminta oleh objek tersebut. Setelah itu, ruang memori yang ditempati oleh objek itu sendiri didaur ulang. Pekerjaan ini diselesaikan oleh kompiler yang memasukkan kode perakitan berikut setelah memanggil destruktor:
hubungi @BeforeDestruction
tes dl, dl
jle+$05
hubungi @ClassDestroy
Pekerjaan yang dilakukan oleh kode-kode ini sesuai dengan apa yang dilakukan ketika membangun objek dan mengalokasikan memori, terutama memanggil fungsi _ClassDestroy pada baris 8997 di system.pas.
Konstruktor dan destruktor
Untuk mendefinisikan konstruktor, gunakan kata kunci Konstruktor. Berdasarkan ketentuan, nama konstruktornya adalah Create (tentu saja nama lain dapat digunakan, tetapi itu bukanlah desain yang bagus!). menyukai:
jenis
TMyFamily = class // Kelas yang ditentukan untuk keluarga Anda
Pribadi
FMyfatherName : String; // nama ayahmu
FMyMotherName : String; // nama ibumu
… // Anggota keluargamu yang lain
Publik
Buat Konstruktor(strNamaAyah, strNamaIbu : String);
...... // Metode lainnya
Akhir;
Anda mungkin bertanya, jika saya tidak menyediakan konstruktor untuk kelas saya, apakah objeknya dapat dibuat? Jawabannya adalah: ya. Alasannya telah disebutkan sebelumnya, alokasi memori yang ditempati oleh objek itu sendiri diselesaikan oleh compiler. Dan karena di Object Pascal, semua kelas (kecuali kelas TObject itu sendiri) diturunkan dari kelas TObject, compiler akan memanggil konstruktor TObject.Create(), tetapi fungsi ini adalah fungsi kosong, dan tidak akan mempengaruhi kelas TMyFamily . Ketika anggota data (FMyfatherName, FMyMotherName) diinisialisasi, mereka akan secara otomatis dihapus ke string kosong (yaitu ''), karena TObject.Create() tidak mengenal ayah atau ibu Anda sama sekali!
Saat membuat objek, konstruktor dipanggil secara langsung, dalam bentuk berikut:
Objek Keluarga Saya := TMyFamily.Create('Zhang', 'Li');
Gunakan kata kunci Destructor untuk mendefinisikan destructor. Berdasarkan konvensi, destructor diberi nama Destroy. menyukai:
jenis
TMyClass = kelas
Publik
Penghancuran Destruktor();
Akhir;
Alasan mengapa pernyataan override ditambahkan di akhir deklarasi destruktor adalah untuk memastikan bahwa objek dapat dirusak dengan benar jika terjadi polimorfisme (polimorfisme akan dibahas secara rinci di Bagian 2.4). Jika Anda tidak menambahkan kata kunci override, kompiler akan memberikan peringatan yang mirip dengan "Metode 'Hancurkan' menyembunyikan metode virtual tipe dasar 'TObject'". Peringatan tersebut berarti bahwa Destroy yang Anda tentukan menyembunyikan metode virtual TObject.Destroy() dari kelas dasar. Dalam hal ini, objek tidak dapat dihancurkan dengan benar dalam situasi polimorfik.
Catatan: Destruktor perlu dideklarasikan dengan pernyataan override.
Demikian pula, jika tidak ada sumber daya khusus yang perlu dilepaskan di kelas Anda, Anda tidak perlu mendefinisikan destruktor. Namun, ketika menghancurkan suatu objek, Anda harus memanggil metode Free() objek tersebut alih-alih memanggil Destroy() secara langsung.
MyFamilyObject.Gratis();
Hal ini karena metode Free() akan menentukan apakah objek itu sendiri nihil, dan jika bukan nihil, Destroy() objek tersebut akan dipanggil untuk meningkatkan keamanan. Sekarang ada cara yang lebih aman untuk melakukan hal ini, tentu tidak ada alasan untuk tidak melakukannya.
Catatan: Jangan pernah memanggil Destroy() secara langsung pada suatu objek, melainkan Free() sebagai gantinya.
Dari sini dapat disimpulkan bahwa dalam Object Pascal Anda hanya perlu memperhatikan alokasi dan pelepasan sumber daya yang digunakan oleh objek tersebut, dan tidak perlu memperdulikan ruang yang ditempati oleh objek itu sendiri!