การวิเคราะห์โครงสร้างและการทำลายล้างใน Delphi
1 โมเดลวัตถุใน Delphi: 2
1.1 ชื่อวัตถุหมายถึงอะไร? 2
1.2 วัตถุเก็บไว้ที่ไหน? 2
1.3 สิ่งที่เก็บไว้ในวัตถุ? พวกเขาเก็บไว้อย่างไร?
2 ตัวสร้างและการสร้างวัตถุ 5
2.1 ตัวสร้างคืออะไร? (วิธีการเรียน "พิเศษ") 5
2.2 กระบวนการทั้งหมดในการสร้างวัตถุ 5
2.3 การใช้งานทางเลือกของตัวสร้าง (ใช้การอ้างอิงคลาสเพื่อใช้ความหลากหลายของตัวสร้าง) 6
3 Destructor and Destruction Object 7
3.1 วิธีการทำลายล้างคืออะไร ("ตามธรรมชาติ" วิธีการเสมือนจริง) 7
3.2 กระบวนการทั้งหมดของการทำลายวัตถุ 7
3.3 ทำลาย, ฟรี, freeandnil, ปล่อยการใช้งานและความแตกต่าง 7
4 VCL Construction & Destructuring Architecture 8
5 ใช้ตัวสร้างและ destructors อย่างถูกต้อง 9
การวิเคราะห์โครงสร้างและการทำลายล้างใน Delphi
บทคัดย่อ: ผ่านการศึกษา VCL/RTL บทความนี้วิเคราะห์กลไกการใช้งานของตัวสร้างและการทำลายล้างและสถาปัตยกรรมของวัตถุใน VCL และอธิบายวิธีการสร้างและปล่อยวัตถุอย่างถูกต้อง
คำสำคัญ: สร้าง, ทำลาย, สร้างวัตถุ, ทำลายวัตถุ, ฮีป, สแต็ก, polymorphism
ผู้แต่ง: Majorsoft
คำถาม
กลไกการใช้งานของผู้สร้างและการทำลายล้างใน Delphi คืออะไร วิธีสร้างและปล่อยวัตถุอย่างถูกต้อง?
สารละลาย
วิธีการใช้งานการก่อสร้างและการทำลายล้างอย่างถูกต้องเป็นปัญหาที่พบบ่อยในกระบวนการใช้ Delphi ต่อไปนี้คือการทำความเข้าใจกลไกการใช้งานของตัวสร้างและการทำลายล้างผ่านการศึกษาซอร์สโค้ด VCL/RTL
1 โมเดลวัตถุใน Delphi:
1.1 ชื่อวัตถุหมายถึงอะไร?
ซึ่งแตกต่างจาก C ++ ชื่อวัตถุ (เรียกอีกอย่างว่าตัวแปร) ใน Delphi แสดงถึงการอ้างอิงของวัตถุและไม่ได้เป็นตัวแทนของวัตถุเองซึ่งเทียบเท่ากับตัวชี้ไปยังวัตถุซึ่งเรียกว่า "โมเดลอ้างอิงวัตถุ" ดังแสดงในรูป:
OBJ (ชื่อวัตถุ) วัตถุจริง
ที่อยู่รายการ VMT
สมาชิกข้อมูล
รูปที่ 1 ชื่อวัตถุหมายถึงวัตถุในหน่วยความจำ
1.2 วัตถุเก็บไว้ที่ไหน?
แต่ละแอปพลิเคชันแบ่งหน่วยความจำที่จัดสรรให้เป็นสี่พื้นที่:
พื้นที่รหัส
พื้นที่ข้อมูลทั่วโลก
พื้นที่กอง
พื้นที่สแต็ค
รูปที่ 2 พื้นที่หน่วยความจำโปรแกรม
พื้นที่รหัส: รหัสโปรแกรมจัดเก็บในโปรแกรมรวมถึงรหัสฟังก์ชันทั้งหมด
พื้นที่ข้อมูลทั่วโลก: เก็บข้อมูลทั่วโลก
ฮีปพื้นที่: หรือที่รู้จักกันในชื่อ "พื้นที่จัดเก็บฟรี" ซึ่งเก็บข้อมูลแบบไดนามิก (รวมถึงวัตถุและสตริงใน Delphi) ขอบเขตคือวงจรชีวิตทั้งหมดของแอปพลิเคชันจนกว่าจะมีการเรียกว่า destructor
พื้นที่สแต็ก: หรือที่รู้จักกันในชื่อ "พื้นที่จัดเก็บอัตโนมัติ" เพื่อจัดเก็บข้อมูลท้องถิ่นในโปรแกรม ขอบเขตอยู่ภายในฟังก์ชั่นและระบบรีไซเคิลพื้นที่สแต็กทันทีหลังจากเรียกใช้ฟังก์ชั่น
ใน C ++ วัตถุสามารถสร้างขึ้นบนกองหรือบนสแต็กหรือในข้อมูลทั่วโลก ใน Delphi วัตถุทั้งหมดถูกสร้างขึ้นบนพื้นที่จัดเก็บฮีปดังนั้นตัวสร้าง Delphi ไม่สามารถเรียกได้โดยอัตโนมัติ แต่ต้องเรียกโดยโปรแกรมเมอร์เอง (ลากส่วนประกอบในนักออกแบบและวัตถุถูกสร้างขึ้นโดย Delphi) โปรแกรมต่อไปนี้อธิบายความแตกต่างระหว่างการสร้างวัตถุใน Delphi และ C ++:
ใน Delphi:
โพรซีเดอร์ createObject (var fooobjref: tfooobject);
เริ่ม
fooobjref: = tfooobject.create;
// เรียกโดยโปรแกรมเมอร์หลังจากขั้นตอนที่เรียกว่าวัตถุยังคงมีอยู่
fooobject.caption = 'ฉันถูกสร้างขึ้นในสแต็กของ createObject ()';
จบ;
และใน C ++:
tfooobject createObject (เป็นโมฆะ);
-
tfooobject fooobject; // สร้างวัตถุในท้องถิ่น
// Static tfooobject fooobject; // สร้างวัตถุท้องถิ่นแบบคงที่
// วัตถุถูกสร้างขึ้นโดยอัตโนมัติโดยเรียกตัวสร้างเริ่มต้นและวัตถุถูกสร้างขึ้นในสแต็กฟังก์ชั่นในเวลานี้
fooobject.caption = 'ฉันถูกสร้างขึ้นในสแต็กของ createObject ()';
กลับ fooobject;
// วัตถุจะถูกคัดลอกเมื่อกลับมาและวัตถุที่สร้างขึ้นดั้งเดิมจะถูกทำลายโดยอัตโนมัติหลังจากการเรียกใช้ฟังก์ชันเสร็จสิ้น}
tfooObject fooobject2; // สร้างวัตถุทั่วโลก
เป็นโมฆะ Main ();
{tfooObject* pfooObject = new tfooObject;
// สร้างวัตถุฮีป หลังจากเรียกฟังก์ชั่นวัตถุยังคงมีอยู่และไม่จำเป็นต้องคัดลอก -
1.3 สิ่งที่เก็บไว้ในวัตถุ? พวกเขาเก็บไว้อย่างไร?
แตกต่างจาก C ++ วัตถุใน Delphi จะจัดเก็บที่อยู่ของสมาชิกข้อมูลและตารางวิธีการเสมือน (VMTs) เท่านั้น แต่ไม่เก็บวิธีการดังแสดงในรูป:
เซ็กเมนต์การใช้เมธอด
ที่อยู่ VMT
ชื่อ: สตริง
ความกว้าง: จำนวนเต็ม;
CH1: Char;
-
Proc1
func1
-
พร็อพ
funcn
-
รูปที่ 3 โครงสร้างของวัตถุ ...
บางทีคุณอาจมีคำถามเกี่ยวกับคำสั่งข้างต้นโปรดดูขั้นตอนต่อไปนี้:
tsizealigntest = คลาส
ส่วนตัว
ฉัน: จำนวนเต็ม;
CH1, CH2: Char;
J: จำนวนเต็ม;
สาธารณะ
ขั้นตอน showmsg;
โพรซีเดอร์ Virtmtd;
จบ;
memo1.lines.add (inttoStr (sizetest.instancesize)+': อินสแตนซ์');
memo1.lines.add (inttoStr (จำนวนเต็ม (sizetest))+'<-เริ่ม addr');
memo1.lines.add (inttoStr (จำนวนเต็ม (@(sizetest.i)))+'<-sizetest.i');
memo1.lines.add (inttoStr (จำนวนเต็ม (@(sizetest.ch1)))+'<-sizetest.ch1');
memo1.lines.add (inttoStr (จำนวนเต็ม (@(sizetest.ch2)))+'<-sizetest.ch2');
memo1.lines.add (inttoStr (จำนวนเต็ม (@(sizetest.j)))+'<-sizetest.j');
ผลลัพธ์แสดง:
16: อินสแตนซ์
14630724 <-start addr
14630728 <-sizetest.i
14630732 <-Sizetest.ch1
14630733 <-Sizetest.ch2
14630736 <-sizetest.j
สมาชิกข้อมูลและที่อยู่ VMT ครอบครอง 16 ไบต์!
แล้วฟังก์ชั่นสมาชิกจะถูกเก็บไว้ที่ไหน? เนื่องจาก Delphi ขึ้นอยู่กับ RTL (ไลบรารีประเภทรันไทม์) ฟังก์ชั่นสมาชิกทั้งหมดจะถูกเก็บไว้ในคลาส ดังนั้นจะค้นหาที่อยู่รายการของฟังก์ชันสมาชิกได้อย่างไร? สำหรับฟังก์ชั่นคงที่งานนี้ทำโดยคอมไพเลอร์ เวลานี้) ต้องมีอยู่ในเวลานี้
สังเกต
ดังที่ได้กล่าวไว้ข้างต้นฟังก์ชั่นสมาชิกทั้งหมดจะถูกเก็บไว้ในชั้นเรียนและรวมถึงตารางวิธีการเสมือนจริง VMT จากฟังก์ชั่นการเติมข้อความอัตโนมัติของ Delphi (ขึ้นอยู่กับข้อมูลการรวบรวม) เราจะเห็นได้ว่าหลังจากที่เราป้อนชื่อวัตถุแล้วป้อน "." Delphi รวบรวมข้อมูลสมาชิกข้อมูลทั้งหมดและวิธีการคงที่ทั้งหมด วิธีการสร้างและการทำลายล้างทั้งหมดคุณสามารถลองใช้งานได้หากเป็นกรณีนี้
ที่อยู่รายการ VMT ของตารางวิธีการเสมือนคลาสคลาส
ข้อมูลแม่แบบสมาชิกข้อมูล
ตารางวิธีการคงที่ ฯลฯ
ตารางวิธีการเสมือน VMT
วัตถุ
ที่อยู่รายการ VMT
สมาชิกข้อมูล
โปรแกรมข้างต้นยังแสดงให้เห็นถึงการจัดตำแหน่งของสมาชิกข้อมูลวัตถุ (โครงสร้างข้อมูลทางกายภาพ) ซึ่งจัดตำแหน่งใน 4 ไบต์ (การจัดตำแหน่งเริ่มต้นของ Windows) ดังแสดงในรูปด้านล่าง:
VMT ทางเข้า addr
ฉัน
CH1CH2
J
2 ตัวสร้างและการสร้างวัตถุ
2.1 ตัวสร้างคืออะไร? (วิธี "พิเศษ")
จากความหมายของแนวคิด OO (เชิงวัตถุ) ตัวสร้างมีหน้าที่รับผิดชอบในการสร้างวัตถุ แต่ในแง่ของการใช้ภาษา OOP ไม่ว่าจะเป็น Delphi หรือ C ++ ตัวสร้างจะเริ่มต้นวัตถุเท่านั้น (รวมถึง การเรียกวัตถุย่อยภายใน)
นอกจากนี้ซึ่งแตกต่างจากใน C ++, Delphi กำหนดวิธีการอื่นสำหรับตัวสร้าง (mkConstructor, ดู Line /Source/RTL/Common/typinfo.pas, บรรทัดที่ 125 ในไดเรกทอรีการติดตั้ง Delphi) ซึ่งเราสามารถเข้าใจได้ว่าเป็นวิธีการเรียน "พิเศษ" . มันสามารถเรียกได้ผ่านคลาส (ชื่อการอ้างอิงคลาส/คลาส/ตัวชี้คลาส) ในขณะที่วิธีการคลาสทั่วไปสามารถเรียกผ่านทั้งคลาสและวัตถุ และในวิธีการเรียนชี้ไปที่ชั้นเรียนซึ่งเรามักจะเริ่มต้นสมาชิกข้อมูลเพื่อให้เป็นวัตถุจริงซึ่งทั้งหมดต้องขอบคุณพารามิเตอร์ตนเอง
โดยค่าเริ่มต้นตัวสร้างเป็นฟังก์ชั่นคงที่ สร้างตัวสร้างหลายตัวและยังสามารถซ้อนทับตัวสร้างของคลาสแม่ในคลาสที่ได้มา ของโครงสร้างและการทำลายล้าง (ดู 4)
2.2 กระบวนการสร้างวัตถุทั้งหมด
กระบวนการที่สมบูรณ์ในการสร้างวัตถุควรรวมถึงการจัดสรรพื้นที่การสร้างโครงสร้างข้อมูลทางกายภาพการเริ่มต้นและการสร้างวัตถุย่อยภายใน ดังที่ได้กล่าวไว้ข้างต้นคอนสตรัคเตอร์มีความรับผิดชอบในการเริ่มต้นและเรียกตัวสร้างของวัตถุย่อยภายใน นี่เป็นเพราะคอมไพเลอร์กำลังทำสิ่งพิเศษเราไม่รู้ เมื่อรวบรวมเข้ากับคอนสตรัคเตอร์ก่อนที่จะสร้างฟังก์ชั่นบรรทัดของ "การโทร @classcreate" จะถูกแทรก ::
ฟังก์ชั่น _classcreate (aclass: tclass; alloc: boolean): tobject;
asm
{ -> eax = ตัวชี้ไปที่ vmt}
{<- eax = ตัวชี้ไปที่อินสแตนซ์}
-
โทรหา dword ptr [eax] .vmtNewInstance // โทร newinstance
-
สิ้นสุด;
VmtNewInstance = -12; มันเป็นฟังก์ชันใหม่ของ Newinstance ในชั้นเรียนจากนั้น "เรียก DWORD PTR [EAX] .VMTNewInstance" จริง ๆ
ฟังก์ชั่นคลาส Newinstance: tobject;
ฟังก์ชั่นคลาส toBject.NewInstance: TOBJECT;
เริ่ม
ผลลัพธ์: = initinstance (_getMem (อินสแตนซ์));
จบ;
"initinstance (_getMem (อินสแตนซ์))" เรียกฟังก์ชั่นสามฟังก์ชั่น:
1) อินสแตนซ์โทรครั้งแรก () เพื่อส่งคืนขนาดวัตถุของคลาสจริง
ฟังก์ชั่นคลาส tobject.instancesize: Longint; // เทียบเท่ากับวิธีการเสมือนจริง
เริ่ม
ผลลัพธ์: = pinteger (จำนวนเต็ม (self) + vmtinstancesize)^; // ส่งคืนขนาดวัตถุของคลาสจริง
จบ;
2) โทร _getMem () เพื่อจัดสรรหน่วยความจำขนาดอินสแตนซ์บนฮีปและส่งคืนการอ้างอิงของวัตถุ
3) การเรียกใช้ initinstance () เพื่อสร้างโครงสร้างข้อมูลทางกายภาพและตั้งค่าเริ่มต้นของสมาชิกเช่นการตั้งค่าของสมาชิกข้อมูลจำนวนเต็มเป็น 0, การตั้งค่าตัวชี้เป็น nil, ฯลฯ หากมีวิธีการเสมือนจริงให้กำหนดที่อยู่รายการของตารางวิธีการเสมือน VMT ให้กับสี่ไบต์แรกของวัตถุ
หลังจากโทรหา Newinstance วัตถุในเวลานี้มี "เชลล์ที่ว่างเปล่า" เท่านั้นและไม่มี "เนื้อหา" จริงดังนั้นจึงจำเป็นต้องเรียกคอนสตรัคเตอร์ที่กำหนดเองเพื่อเริ่มต้นวัตถุอย่างมีความหมายและเรียกตัวสร้างของวัตถุย่อยภายในเปิดใช้งาน วัตถุในโปรแกรมเพื่อสะท้อนวัตถุอย่างแท้จริงในโลกแห่งความเป็นจริง นี่คือกระบวนการทั้งหมดของการสร้างวัตถุ
2.3 การใช้งานทางเลือกของตัวสร้าง (ใช้การอ้างอิงคลาสเพื่อใช้ความหลากหลายของตัวสร้าง)
ใน Delphi ชั้นเรียนจะถูกเก็บไว้เป็นวัตถุดังนั้นจึงมีความหลากหลาย ตั้งค่าเมธอดคลาสเป็นวิธีการเสมือนจริงแทนที่ในคลาสที่ได้รับจากนั้นเรียกมันผ่านการอ้างอิง/ตัวชี้ของคลาสฐานเพื่อให้วัตถุถูกสร้างขึ้นตามการอ้างอิงคลาส/ตัวชี้ที่ชี้ไปที่คลาสจริง โปรดดูโปรแกรมต่อไปนี้:
tmyclass = คลาส
ตัวสร้างสร้าง; เสมือนจริง;
จบ;
ttmyclass = คลาสของ tmyclass; // การอ้างอิงคลาสของคลาสฐาน
tmyclasssub = คลาส (tmyclass)
ตัวสร้างสร้าง;
จบ;
โพรซีเดอร์ createObj (aclass: ttmyclass; var ref);
เริ่ม
tobject (อ้างอิง): = aclass.create;
// REF ไม่มีประเภทและไม่เข้ากันกับทุกประเภทดังนั้นจึงต้องถูกคัดเลือกอย่างชัดเจนเมื่อใช้ (Cast)
// ACLASS เป็นข้อมูลอ้างอิงคลาสอินเทอร์เฟซฟังก์ชั่นแบบครบวงจรและการใช้งานที่แตกต่างกัน
// มันจะสร้างวัตถุตามคลาสที่อ้างอิง/ชี้ไปที่ ACLASS
จบ;
-
createobj (tmyclass, obj);
createobj (tmyclasssub, subobj);
3 destructor และทำลายวัตถุ
3.1 วิธีการทำลายล้างคืออะไร ("ตามธรรมชาติ" วิธีการเสมือนจริง)
การพูดแบบความหมาย Destructor มีหน้าที่ในการทำลายวัตถุและปล่อยทรัพยากร ใน Delphi มีความหมายเหมือนกัน
Delphi ยังกำหนดประเภทวิธีการสำหรับ destructor (mkconstructor, ดู line /source/rtl/common/typinfo.pas, 125 ในไดเรกทอรีการติดตั้ง Delphi) ; ทำไม VCL ถึงทำเช่นนี้? เพราะมันทำให้มั่นใจได้ว่าวัตถุสามารถถูกทำลายอย่างถูกต้องในสถานการณ์ polymorphic หากไม่ได้ใช้วิธีการเสมือนจริงคุณอาจทำลาย subobject คลาสฐานเท่านั้นส่งผลให้ "การรั่วไหลของหน่วยความจำ" ที่เรียกว่า ดังนั้นเพื่อให้แน่ใจว่าการทำลายล้างที่ถูกต้องผู้ทำลายจำเป็นต้องเพิ่มการประกาศแทนที่
3.2 กระบวนการทำลายวัตถุทั้งหมด
ก่อนอื่นทำลาย subobject คลาสที่ได้รับจากนั้นทำลาย subobject คลาสฐาน
คำใบ้
ในคลาสที่ได้รับวัตถุย่อยคลาสพื้นฐานหมายถึงส่วนที่สืบทอดมาจากคลาสฐานและวัตถุลูกในคลาสที่ได้รับหมายถึงส่วนที่เพิ่มใหม่
3.3 ทำลาย, ฟรี, freeandnil, ปล่อยการใช้งานและความแตกต่าง
ทำลาย: วิธีการเสมือนจริง
หน่วยความจำที่วางจำหน่ายประกาศว่าเป็นเสมือนจริงใน tobject มักจะแทนที่ในคลาสย่อยและเพิ่มคำหลักที่สืบทอดมาเพื่อให้แน่ใจว่าวัตถุคลาสที่ได้รับถูกทำลายอย่างถูกต้อง
แต่การทำลายไม่สามารถใช้โดยตรงทำไม?
หากวัตถุไม่มีเรายังคงเรียกทำลายข้อผิดพลาดจะเกิดขึ้น เนื่องจากการทำลายเป็นวิธีการเสมือนจริงจึงจำเป็นต้องค้นหาที่อยู่ทางเข้าของตารางวิธีการเสมือน VMT ตามสี่ไบต์แรกในวัตถุเพื่อค้นหาที่อยู่ทางเข้าของการทำลายดังนั้นวัตถุจะต้องมีอยู่ในเวลานี้ แต่ฟรีเป็นวิธีการคงที่ การใช้ฟรีนั้นปลอดภัยกว่าการใช้ทำลาย
2) ฟรี: วิธีการคงที่
ทดสอบว่าวัตถุนั้นไม่มีหรือไม่และการทำลายจะเรียกว่าถ้ามันไม่ได้เป็นศูนย์ นี่คือรหัส Delphi ฟรี:
ขั้นตอน tobject.free;
เริ่ม
ถ้าตัวเอง <> ไม่มี
ทำลาย;
จบ;
การเรียนรู้จากจุดแข็งและจุดอ่อนของคน ๆ หนึ่งหรือไม่
อย่างไรก็ตามการโทรทำลายเพียงแค่ทำลายวัตถุ แต่ไม่ได้ตั้งค่าการอ้างอิงของวัตถุให้เป็นศูนย์ซึ่งต้องทำโดยโปรแกรมเมอร์
3) Freeandnil; วิธีการทั่วไป, วิธีที่ไม่ใช่วัตถุ, วิธีที่ไม่ใช่คลาส
คำจำกัดความของ Freeandnil ในหน่วย sysutils
ขั้นตอน Freeandnil (var obj);
วาจา
อุณหภูมิ: tobject;
เริ่ม
อุณหภูมิ: = tobject (obj);
ตัวชี้ (obj): = nil;
Temp.free;
จบ;
เราขอแนะนำให้คุณใช้แทนฟรี/ทำลายเพื่อให้แน่ใจว่าวัตถุนั้นถูกปล่อยออกมาอย่างถูกต้อง
4) การเปิดตัว;
ฟังก์ชั่นฟรีเรียกว่าหลังจากเหตุการณ์ทั้งหมดในหน้าต่างถูกประมวลผล มันมักจะใช้ในการทำลาย Windows และเมื่อการประมวลผลเหตุการณ์ใช้เวลาในหน้าต่างนี้เป็นระยะเวลาหนึ่งวิธีนี้สามารถมั่นใจได้ว่าหน้าต่างจะถูกทำลายหลังจากการประมวลผลของหน้าต่างเท่านั้น นี่คือซอร์สโค้ด Delphi ของ tcustomform.release:
ขั้นตอน tcustomform.release;
เริ่ม
postmessage (handle, cm_release, 0, 0);
// ส่งข้อความ CM_RELEASE ไปที่หน้าต่างไปยังคิวข้อความ
// โทร cm_release processing processing กระบวนการ cmrelease อีกครั้ง
จบ;
มาดูคำจำกัดความของ cmrelease ต่อไปนี้สำหรับการประมวลผลข้อความ cm_release:
โพรซีเดอร์ cmrelease (ข้อความ var: tmessage); ข้อความ cm_release;
ขั้นตอน tcustomform.cmrelease;
เริ่ม
ฟรี; // ในที่สุดมันก็ฟรี
จบ;
4 VCL การก่อสร้างและการทำลายโครงสร้างสถาปัตยกรรม
ยาสูบ
ตัวสร้างสร้าง; // วิธีการคงที่
Destructor ทำลาย;
tpersistent
Destructor ทำลาย;
tComponent
ตัวสร้างสร้าง (AOWNER: TCOMPONENT);
Destructor ทำลาย;
tcontrol
ตัวสร้างสร้าง (AOWNER: TCOMPONENT);
Destructor ทำลาย;
-
ต่อไปนี้วิเคราะห์ซอร์สโค้ดของการก่อสร้างและการทำลายโครงสร้างใน VCL โดยใช้ TCONTROL เป็นตัวอย่าง:
constructor tcontrol.create (AOWNER: TCOMPONENT);
เริ่ม
สืบทอดมาสร้าง (aowner); // สร้างคลาสฐาน subobject และส่งมอบสิทธิการทำลายล้างให้กับเจ้าของ วางไว้ข้างหน้า
// สิ่งนี้ทำให้มั่นใจได้ว่าคำสั่งของ "การสร้าง subobject คลาสฐานก่อนจากนั้นสร้างคลาส subobjects ที่ได้รับ"
… // เริ่มต้นและเรียกตัวสร้างของ subobject ภายใน
จบ;
destructor tcontrol.destroy;
เริ่ม
… // destruct subobjects ภายในในชั้นเรียนที่ได้รับ
Destroy ที่สืบทอดมา; // ทำลายวัตถุคลาสฐานและวางไว้ในตอนท้าย
// สิ่งนี้ทำให้มั่นใจได้ว่าคำสั่งของ "การทำลายครั้งแรกของ subobjects คลาสที่ได้รับจากนั้นการทำลายล้างระดับฐานย่อย"
จบ;
5 ใช้ตัวสร้างและตัวทำลายอย่างถูกต้อง
หลังจากการวิเคราะห์ข้างต้นดังต่อไปนี้สรุปหลักการของการใช้ตัวสร้างและการทำลายล้าง:
ก่อนที่จะใช้วัตถุคุณต้องสร้างวัตถุก่อนและทำลายวัตถุในเวลาเพื่อเพิ่มทรัพยากร
เมื่อวัตถุสองชิ้นอ้างถึงการกำหนดตรวจสอบให้แน่ใจว่าวัตถุนิรนาม (หมายถึงวัตถุที่ไม่ได้อ้างอิง) ที่ปรากฏสามารถปล่อยออกมาได้
เมื่อสร้างส่วนประกอบขอแนะนำให้ตั้งค่าส่วนประกอบโฮสต์ (นั่นคือใช้พารามิเตอร์ AOWNER โดยปกติจะเป็นรูปแบบ) และ AONDER จัดการการทำลายวัตถุดังนั้นไม่จำเป็นต้องกังวลเกี่ยวกับการทำลายส่วนประกอบ Delphi ในการออกแบบโมดูลฟอร์ม/ข้อมูลและสร้างส่วนประกอบเป็นวิธีที่ใช้ ดังนั้นเราไม่จำเป็นต้องเขียน destructor ที่เรียกองค์ประกอบ
เมื่อประเภทการส่งคืนของฟังก์ชั่นเป็นวัตถุผลลัพธ์ก็เป็นการอ้างอิงถึงวัตถุเพื่อให้มั่นใจว่าวัตถุที่อ้างอิงโดยผลลัพธ์จะต้องมีอยู่
หากต้องการใช้ obj <> nil หรือที่ได้รับมอบหมาย (ไม่มี) เพื่อทดสอบว่าวัตถุนั้นมีอยู่, OBJ: = NIL ก็ควรเรียกหลังจาก OBJ: = NIL
โปรดดูที่ซอร์สโค้ดของโปรแกรมสาธิต
คำแนะนำ (แนะนำ)
โปรแกรม Delphi ทั้งหมดถูกส่งผ่านไปยัง Win2K+Delphi6 SP2 เพื่อให้เข้าใจบทความนี้ลึกซึ้งยิ่งขึ้นขอแนะนำให้อ้างถึงโปรแกรมการสาธิต
บทความนี้รวมถึงประสบการณ์และประสบการณ์ของฉันในการเรียนรู้ VCL/RTL นอกจากนี้ความสามารถส่วนตัวของฉันมี จำกัด
ก่อนที่จะอ่านบทความนี้ผู้อ่านจะต้องมีความเข้าใจบางอย่างเกี่ยวกับภาษาปาสกาลที่มุ่งเน้นและสามารถเข้าใจความหลากหลาย
ผ่านบทความนี้คุณควรจะสามารถเข้าใจแบบจำลองวัตถุกลไกการก่อสร้างและการทำลายโครงสร้างใน Delphi และสถาปัตยกรรมการก่อสร้างและการทำลายล้างใน VCL และสามารถใช้วิธีการก่อสร้างและการทำลายโครงสร้างได้ โครงสร้างและการทำลายล้างใน Delphi นั้นง่ายกว่าใน C ++ มากและเราควรจะสามารถควบคุมได้