Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

ทำไมต้องมี Pure Virtual Destructor ใน C++?

Pure virtual destructor เป็นกลไกสำคัญในการทำให้คลาสกลายเป็น Abstract Class พร้อมทั้งรับประกันการทำลายออบเจกต์อย่างถูกต้อง

ทำไมต้องมี Body (Definition)?

ใน C++ Destructor ถูกเรียกแบบ **chain** จาก derived ไป base:

~Derived() -> ~Base()

แม้ Base destructor จะเป็น pure virtual (= 0) ก็ยังถูกเรียก ดังนั้น **ต้องมี definition** ไม่งั้นจะ linker error

ตัวอย่างโค้ด

#include <iostream>

using namespace std;

class Base {
public:
    virtual ~Base() = 0;  // Pure virtual destructor
};

// ต้องมี definition แยกต่างหาก (แม้จะเป็น pure virtual)
Base::~Base() {
    cout << "Base::~Base() called (pure virtual destructor body)" << endl;
}

class Derived : public Base {
public:
    ~Derived() override {
        cout << "Derived::~Derived() called" << endl;
    }
};

int main() {
    Base* ptr = new Derived();
    delete ptr;  // เรียก ~Derived() แล้วตามด้วย ~Base()
    
    return 0;
}

ผลลัพธ์

Derived::~Derived() called
Base::~Base() called (pure virtual destructor body)

ทำไมต้องทำ Pure Virtual Destructor?

  1. ทำให้คลาสเป็น Abstract: ไม่สามารถสร้างออบเจกต์ Base ได้โดยตรง
  2. บังคับ Derived ให้ implement destructor: (แต่ destructor มักจะไม่ต้องเขียน ถ้าไม่มี resource ต้องจัดการ)
  3. Polymorphic deletion: ลบผ่าน Base pointer ได้ถูกต้อง

เปรียบเทียบ: Virtual Destructor vs Pure Virtual Destructor

คุณสมบัติVirtual DestructorPure Virtual Destructor
Syntaxvirtual ~Base() {}virtual ~Base() = 0; + definition
Class เป็น Abstract?ไม่ (ยกเว้นมี pure virtual อื่น)ใช่ (เสมอ)
สามารถสร้าง Base object ได้?ได้ไม่ได้
ต้องมี definition?ได้ในบรรทัดเดียวต้องแยก (definition required)
ใช้เมื่อไหร่Base class ธรรมดาที่ต้องการ polymorphic deleteต้องการบังคับให้ subclass เท่านั้นที่สร้างได้

Common Mistake: ลืม Definition

class Base {
public:
    virtual ~Base() = 0;  // ❌ Linker error: undefined reference to `Base::~Base()'
};

// ต้องมี:
Base::~Base() {}  // ✅ Definition (แม้จะว่าง)

Best Practice

class AbstractBase {
public:
    // Pure virtual functions...
    virtual void doSomething() = 0;
    
    // Virtual destructor (ไม่จำเป็นต้อง pure ถ้ามี pure virtual อื่นแล้ว)
    virtual ~AbstractBase() = default;  // C++11: default implementation
    
    // หรือถ้าต้องการ pure virtual destructor:
    // virtual ~AbstractBase() = 0;
};

// ถ้าใช้ pure virtual destructor:
AbstractBase::~AbstractBase() = default;  // Definition (C++11)

สรุป

Pure virtual destructor ใช้เมื่อต้องการทำให้คลาสเป็น Abstract **และ** ต้องการ polymorphic deletion ทำงานได้ถูกต้อง จำเป็นต้อง provide definition (แม้จะว่าง) เพราะ destructor chain จะเรียก base destructor เสมอ