ใน Object Pascal อ็อบเจ็กต์ทั้งหมดจะถูกสร้างขึ้นในพื้นที่ฮีปของหน่วยความจำ แทนที่จะสร้างบนสแต็ก ดังนั้นตัวสร้างจะไม่ถูกเรียกโดยอัตโนมัติโดยคอมไพเลอร์เช่น C++ การสร้างวัตถุและการทำลายวัตถุเป็นความรับผิดชอบของโปรแกรมเมอร์
ในการสร้างวัตถุ คุณต้องจัดสรรหน่วยความจำสำหรับวัตถุก่อน ขั้นตอนนี้ได้รับการสนับสนุนโดยคอมไพเลอร์ใน Object Pascal หรือที่เรียกว่า "Compiler Magic" Magic)" โปรแกรมเมอร์ไม่จำเป็นต้องเข้าร่วมในกระบวนการนี้ จากนั้นสมาชิกข้อมูลของออบเจ็กต์จะต้องเริ่มต้นได้ และคอมไพลเลอร์จะรับผิดชอบในการ "ล้าง" ข้อมูลเหล่านั้น แต่หากมีงานพิเศษก็สามารถดำเนินการให้เสร็จสิ้นได้ ในตัวสร้าง เมื่อวัตถุถูกทำลาย ทรัพยากรที่ร้องขอ (ไม่ใช่หน่วยความจำที่ถูกครอบครองโดยวัตถุนั้นเอง) จะต้องถูกปล่อยออกมา งานเหล่านี้เป็นความรับผิดชอบของผู้ทำลายล้าง "เวทย์มนตร์คอมไพเลอร์"
การจัดสรรและการรีไซเคิลหน่วยความจำอ็อบเจ็กต์
เมื่อคอมไพเลอร์จัดสรรหน่วยความจำให้กับอ็อบเจ็กต์ การสนับสนุนที่มีให้คือการแทรกบรรทัดโค้ดแอสเซมบลีเหล่านี้ก่อนที่จะเรียกตัวสร้าง:
ทดสอบ ดล, ดล
เจซ +$08
เพิ่ม esp, -$10
call @ClassCreate // ให้ความสนใจกับโค้ดบรรทัดนี้
บรรทัดสุดท้ายของโค้ดด้านบนเรียกฟังก์ชัน _ClassCreate ในบรรทัด 8949 ของไฟล์ system.pas (ขึ้นอยู่กับ Delphi 6) ฟังก์ชันนี้จัดสรรหน่วยความจำที่เหมาะสมสำหรับแต่ละวัตถุโดยเฉพาะ หลังจากการจัดสรรหน่วยความจำเสร็จสิ้น ตัวสร้างของคลาสจะถูกเรียกเพื่อเริ่มต้นสมาชิกข้อมูล หลังจากนั้นคอมไพเลอร์จะแทรกบรรทัดโค้ดแอสเซมบลีต่อไปนี้:
ทดสอบ ดล, ดล
เจซ +$0f
โทร @AfterConstruction
ป๊อป dWord ptr fs:[$00000000]
เพิ่ม esp, $0c
งานหลักคือการเรียก AfterConstruction ของแต่ละอินสแตนซ์การเรียกนี้ไม่มีประโยชน์ใน Delphi
ในทำนองเดียวกัน เมื่อทำลายวัตถุ จะต้องเรียกตัวทำลายล้างของคลาสก่อนเพื่อปล่อยทรัพยากรที่ร้องขอโดยวัตถุ หลังจากนั้นพื้นที่หน่วยความจำที่วัตถุครอบครองนั้นจะถูกรีไซเคิล งานนี้เสร็จสมบูรณ์โดยคอมไพเลอร์โดยแทรกโค้ดแอสเซมบลีต่อไปนี้หลังจากเรียก destructor:
โทรหา @BeforeDestruction
ทดสอบ ดล, ดล
เจแอล +$05
โทร @ClassDestroy
งานที่ทำโดยโค้ดเหล่านี้สอดคล้องกับสิ่งที่ทำเมื่อสร้างอ็อบเจ็กต์และการจัดสรรหน่วยความจำ โดยส่วนใหญ่จะเรียกฟังก์ชัน _ClassDestroy บนบรรทัด 8997 ใน system.pas
ตัวสร้างและตัวทำลาย
ในการกำหนดคอนสตรัคเตอร์ ให้ใช้คีย์เวิร์ด Constructor ตามแบบแผน ชื่อของคอนสตรัคเตอร์คือ Create (แน่นอนว่าสามารถใช้ชื่ออื่นได้ แต่นั่นไม่ใช่การออกแบบที่ดีเลย!) ชอบ:
พิมพ์
TMyFamily = class // คลาสที่กำหนดสำหรับครอบครัวของคุณ
ส่วนตัว
FMyFatherName : String; // ชื่อพ่อของคุณ
FMyMotherName : String; // ชื่อคุณแม่ของคุณ
… // สมาชิกคนอื่น ๆ ในครอบครัวของคุณ
สาธารณะ
ตัวสร้างสร้าง (strFatherName, strMotherName : String);
…… // วิธีการอื่นๆ
จบ;
คุณอาจถามว่าถ้าฉันไม่ได้จัดเตรียม Constructor สำหรับคลาสของฉัน จะสร้างอ็อบเจ็กต์ของมันได้หรือไม่ คำตอบคือ: ใช่ มีการกล่าวถึงเหตุผลก่อนหน้านี้ การจัดสรรหน่วยความจำที่วัตถุครอบครองนั้นเสร็จสมบูรณ์โดยคอมไพเลอร์ และเนื่องจากใน Object Pascal คลาสทั้งหมด (ยกเว้นคลาส TObject เอง) ได้มาจากคลาส TObject คอมไพเลอร์จะเรียกตัวสร้าง TObject.Create() แต่ฟังก์ชันนี้เป็นฟังก์ชันว่าง และจะไม่ส่งผลกระทบต่อคลาส TMyFamily เมื่อสมาชิกข้อมูล (FMyFatherName, FMyMotherName) ถูกเตรียมใช้งาน พวกเขาจะถูกล้างเป็นสตริงว่างโดยอัตโนมัติ (เช่น '') เนื่องจาก TObject.Create() ไม่รู้จักพ่อหรือแม่ของคุณเลย!
เมื่อสร้างวัตถุ ตัวสร้างจะถูกเรียกโดยตรง ในรูปแบบต่อไปนี้:
MyFamilyObject := TMyFamily.Create('จาง', 'Li');
หากต้องการกำหนด destructor ให้ใช้คีย์เวิร์ด Destructor ตามแบบแผน destructor จะมีชื่อว่า Destroy ชอบ:
พิมพ์
TMyClass = คลาส
สาธารณะ
ทำลายล้าง();
จบ;
เหตุผลที่เพิ่มคำสั่งแทนที่ในตอนท้ายของการประกาศ destructor คือเพื่อให้แน่ใจว่าวัตถุสามารถทำลายได้อย่างถูกต้องในกรณีของความหลากหลาย (polymorphism จะกล่าวถึงรายละเอียดในหัวข้อ 2.4) หากคุณไม่เพิ่มคีย์เวิร์ดแทนที่ คอมไพเลอร์จะให้คำเตือนคล้ายกับ "วิธีการ 'ทำลาย' ซ่อนวิธีการเสมือนประเภทพื้นฐาน 'TObject'" คำเตือนหมายความว่า Destroy ที่คุณกำหนดจะซ่อนเมธอดเสมือน TObject.Destroy() ของคลาสพื้นฐาน ในกรณีนั้น วัตถุจะไม่สามารถทำลายได้อย่างถูกต้องในสถานการณ์ polymorphic
หมายเหตุ: จำเป็นต้องประกาศตัวทำลายด้วยคำสั่งแทนที่
ในทำนองเดียวกัน หากไม่มีทรัพยากรพิเศษที่จำเป็นต้องเผยแพร่ในชั้นเรียนของคุณ คุณไม่จำเป็นต้องกำหนด destructor อย่างไรก็ตาม เมื่อทำลายวัตถุ คุณควรเรียกใช้เมธอด Free() ของวัตถุ แทนที่จะเรียก Destroy() โดยตรง
MyFamilyObject.Free();
เนื่องจากเมธอด Free() จะกำหนดว่าอ็อบเจ็กต์นั้นเป็นศูนย์หรือไม่ และหากไม่ใช่ศูนย์ ก็จะเรียก Destroy() ของอ็อบเจ็กต์เพื่อเพิ่มความปลอดภัย ขณะนี้มีวิธีที่ปลอดภัยกว่าในการทำเช่นนี้ ก็ไม่มีเหตุผลที่จะไม่ทำเช่นนั้นอย่างแน่นอน
หมายเหตุ: ห้ามเรียก Destroy() บนอ็อบเจ็กต์โดยตรง แต่ให้เรียก Free() แทน
สรุปได้ว่าใน Object Pascal คุณเพียงแค่ต้องใส่ใจกับการจัดสรรและปล่อยทรัพยากรที่วัตถุใช้ และไม่จำเป็นต้องสนใจพื้นที่ที่วัตถุครอบครอง!