การเรียก Child Destructors อย่างชัดเจนยังเรียก Parent Destructors ด้วย

สำหรับตัวจัดการหน่วยความจำที่ฉันเขียนด้วยภาษา C++ เพื่อพิสูจน์แนวคิด เพื่อติดตามอ็อบเจ็กต์ที่ได้รับการจัดสรร ฉันกำลังจัดสรรหน่วยความจำด้วย malloc() ในฟังก์ชัน จากนั้นส่งคืนตัวชี้ไปที่หน่วยความจำนั้น และใช้ตัวดำเนินการวางตำแหน่งใหม่ จากนั้น เพื่อติดตามเมื่อวัตถุถูกลบ ฉันจะส่งตัวชี้ไปยังฟังก์ชันอื่นเพื่อเรียก free() บนตัวชี้

อย่างไรก็ตาม เนื่องจากฉันใช้ free() แทน delete ตัวสร้างของวัตถุจึงไม่ถูกเรียกโดยอัตโนมัติเหมือนปกติ ดังนั้นฉันต้องเรียกมันเอง นอกจากนี้ เนื่องจากตัวจัดการหน่วยความจำได้รับการออกแบบให้ทำงานกับออบเจ็กต์ใดๆ จึงมีความเป็นไปได้ (และเป็นไปได้ด้วยซ้ำ) ว่า ณ จุดหนึ่งของชีวิต จะต้องปล่อยออบเจ็กต์ที่อาจมีคลาสพาเรนต์หลายคลาสหรืออยู่ลึกเข้าไปในแผนผังการสืบทอด

วิธีแก้ปัญหาเริ่มต้นของฉันสำหรับสิ่งนี้คือการเรียกตัวทำลายวัตถุฐานซึ่งจะเรียกตัวทำลายลูกทั้งหมด (หาก คำถามนี้เป็นสิ่งที่ต้องเชื่อ) แต่เนื่องจากวัตถุอาจเป็นอะไรก็ได้อย่างแท้จริงและมีชุดการสืบทอดใดๆ จึงไม่มีทางรู้ได้ว่าคลาสพื้นฐานที่แท้จริงของมันคืออะไร เป็น.

ดังนั้นคำถามของฉันคือ: จะเรียก destructor คลาสย่อยอย่างชัดเจนจะเรียก destructor ฐานทั้งหมดโดยอัตโนมัติเช่นกัน เช่นเดียวกับการ Delete หรือไม่มีทางที่จะทำเช่นนี้ได้ง่าย ๆ หรือไม่?


person sm81095    schedule 24.10.2014    source แหล่งที่มา
comment
ลักษณะการทำงานของการเรียก destructor อัตโนมัติไม่มีความแตกต่างเมื่อเปรียบเทียบกับการเรียกตัวสร้างด้วยตนเอง (อย่างน้อยก็ไม่มีเลยที่ฉันทราบ) การพิสูจน์ว่า (ด้วย Standardese) อาจเป็นเรื่องยาก   -  person dyp    schedule 25.10.2014
comment
มันจะง่ายมากสำหรับคุณที่จะเขียนโค้ดเพื่อค้นหา   -  person Paul Rooney    schedule 25.10.2014
comment
@PaulRooney นั่นไม่ได้ให้การรับประกันใด ๆ แก่คุณ   -  person dyp    schedule 25.10.2014


คำตอบ (1)


ใช่รับประกันแล้ว C++14 [class.dtor]/8:

หลังจากดำเนินการเนื้อความของ destructor และทำลายอ็อบเจ็กต์อัตโนมัติใด ๆ ที่จัดสรรไว้ภายในเนื้อความ destructor สำหรับคลาส X จะเรียก destructor สำหรับสมาชิกข้อมูลที่ไม่ใช่ตัวแปรโดยตรงที่ไม่ใช่ตัวแปรคงที่ของ X ตัว destructors สำหรับคลาสฐานโดยตรงของ X และหาก X เป็น ประเภทของคลาสที่ได้รับมากที่สุด (12.6.2) destructor จะเรียก destructors สำหรับคลาสพื้นฐานเสมือนของ X

โดยเฉพาะสำหรับประเภท T ใดๆ คุณสามารถทำสิ่งนี้ได้ตลอดเวลา:

void * addr = ::operator new(sizeof T);
T * p = ::new (addr) T(/* ctor args */);
p->~T();                                    // !
::operator delete(addr);

หรือหากคุณไม่ต้องการเรียกใช้ตัวจัดสรร:

{
    std::aligned_storage_t<sizeof(T), alignof(T)> storage;
    T * p = ::new (static_cast<void *>(std::addressof(storage))) T(/* args */);
    p->~T();
}
person Kerrek SB    schedule 24.10.2014
comment
จริงๆ แล้วฉันมีคำถามสั้นๆ สองข้อเกี่ยวกับเรื่องนั้น 1. นี่เป็นสำหรับ C++14 แต่รับประกันสำหรับ C++11 ที่ฉันใช้ด้วยหรือไม่ 2. สิ่งนี้บอกว่าจะทำอย่างนั้น แต่ไม่ได้บอกอย่างชัดเจนว่าสิ่งนี้จะเกิดขึ้นสำหรับการโทรที่ชัดเจน ดังนั้นรับประกันหรือนี่พูดถึง delete เท่านั้น - person sm81095; 25.10.2014
comment
@ sm81095: 1) ใช่ 2) มันไม่ได้พูดถึง delete; มันพูดถึงผู้ทำลายล้าง - person Kerrek SB; 25.10.2014
comment
โอเค เจ๋งมาก! ขอบคุณสำหรับคำตอบที่รวดเร็วและตรงไปตรงมา ฉันจะทำการทดสอบหลายอย่างกับสิ่งนี้ แต่เนื่องจากมันเป็นส่วนหนึ่งของมาตรฐาน ฉันจึงคาดหวังว่าทุกอย่างจะได้ผล - person sm81095; 25.10.2014
comment
@sm81095: ลืมเรื่องนั้นไปซะเถอะ นี่เป็นส่วนหลักที่ลึกซึ้งของโมเดลออบเจ็กต์ทั้งหมดของภาษาจนไม่น่าเชื่อเลยที่คอมไพเลอร์จะได้รับส่วนใดส่วนหนึ่งของข้อผิดพลาดนี้ - person Kerrek SB; 25.10.2014