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

Pure Virtual Destructor ใน C++: ความจำเป็นและการใช้งาน

Pure virtual destructor เป็นเทคนิคทำให้คลาสเป็น **Abstract** พร้อมรับประกัน **Polymorphic Deletion** ทำงานถูกต้อง

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

  1. ทำให้คลาสเป็น Abstract:
  2. บังคับ Polymorphic Deletion: ลบผ่าน base pointer ได้ถูกต้อง
  3. การทำลายแบบ Chain: ~Derived() → ~Base() ต้องมี base destructor body

กฎสำคัญ: Pure Virtual Destructor ต้องมี Definition

class Base {
public:
    virtual ~Base() = 0;  // Declaration: pure virtual
};

// Definition จำเป็นต้องมี (แม้จะเป็น pure virtual)
Base::~Base() {
    cout << "Base::~Base() called\n";
}

หากไม่มี definition → **Linker Error**: `undefined reference to Base::~Base()`

ตัวอย่างครบถ้วน

#include <iostream>
#include <memory>

using namespace std;

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

// ต้อง provide definition
Base::~Base() {
    cout << "Base destructor called\n";
}

class DerivedA : public Base {
    int id;
public:
    DerivedA(int i) : id(i) {}
    ~DerivedA() override { cout << "DerivedA(" << id << ") destructor\n"; }
    void identify() const override { cout << "DerivedA(" << id << ")\n"; }
};

class DerivedB : public Base {
    string name;
public:
    DerivedB(string n) : name(move(n)) {}
    ~DerivedB() override { cout << "DerivedB(" << name << ") destructor\n"; }
    void identify() const override { cout << "DerivedB(" << name << ")\n"; }
};

int main() {
    // Base b;  // ❌ Error: abstract class
    
    unique_ptr<Base> ptr1 = make_unique<DerivedA>(42);
    unique_ptr<Base> ptr2 = make_unique<DerivedB>("test");
    
    ptr1->identify();
    ptr2->identify();
    
    cout << "--- Deleting ---\n";
    // Destructors called automatically via unique_ptr
    // Order: ~DerivedA() -> ~Base(), ~DerivedB() -> ~Base()
    
    return 0;
}

ผลลัพธ์

DerivedA(42)
DerivedB(test)
--- Deleting ---
DerivedA(42) destructor
Base destructor called
DerivedB(test) destructor
Base destructor called

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

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

C++11/14/17/20 Syntax

// C++11: default implementation
class Base {
public:
    virtual ~Base() = 0;
};
Base::~Base() = default;  // Definition

// หรือรวมใน class (C++11)
class Base {
public:
    virtual ~Base() = default;  // ไม่ใช่ pure virtual แตก็ทำให้เป็น abstract ได้ถ้ามี pure virtual อื่น
};

// Pure virtual destructor แบบเต็ม
class AbstractBase {
public:
    virtual void foo() = 0;
    virtual ~AbstractBase() = 0;
};
AbstractBase::~AbstractBase() = default;  // Definition

Common Mistake

class Base {
public:
    virtual ~Base() = 0;  // ❌ Missing definition!
};

// Base::~Base() {}  // ต้องมี definition นี้
// ไม่งั้น linker error: undefined reference to `Base::~Base()' 

เมื่อไหร่ควรใช้ Pure Virtual Destructor?

  • ออกแบบ **Interface Class** (มีแต่ pure virtual functions)
  • ต้องการ **บังคับ** ให้สร้างได้เฉพาะ derived classes
  • ต้องการ **polymorphic deletion** ผ่าน base pointer
  • Base class ไม่มี state ของตัวเอง (pure interface)

สรุป

Pure virtual destructor = **Abstract class marker** + **Polymorphic deletion enabler**
**จำเป็นต้องมี definition** (แม้จะ = default) เพราะ destructor chain จะเรียก base destructor เสมอ