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

ความแตกต่างระหว่าง Virtual Function และ Pure Virtual Function ใน C++

Virtual function และ Pure virtual function ทั้งคู่ใช้สำหรับ polymorphism แต่มีจุดประสงค์และข้อกำหนดที่แตกต่างกัน

ตารางเปรียบเทียบ

คุณสมบัติVirtual FunctionPure Virtual Function
Syntaxvirtual void foo() { ... }virtual void foo() = 0;
Implementation ใน Baseมี (optional override)ไม่มี (ต้อง override ใน derived)
Class TypeConcrete (สามารถ instantiate ได้)Abstract (ไม่สามารถ instantiate ได้)
Derived Class ObligationOverride ได้ ไม่บังคับ**ต้อง** override (มิฉะนั้น derived ก็เป็น abstract)
PurposeDefault behavior + polymorphismDefine interface/contract
V-table EntryPointer ไป function bodyNULL (หรือ pointer ไป pure virtual thunk)

ตัวอย่าง Virtual Function (Regular)

#include <iostream>

using namespace std;

class Animal {
public:
    virtual void makeSound() {  // Virtual with default implementation
        cout << "Some generic animal sound\n";
    }
    virtual ~Animal() = default;
};

class Dog : public Animal {
public:
    void makeSound() override {
        cout << "Woof!\n";
    }
};

class Cat : public Animal {
public:
    void makeSound() override {
        cout << "Meow!\n";
    }
};

// ใช้ base implementation
class SilentAnimal : public Animal {
    // ไม่ override makeSound() - ใช้ base version
};

int main() {
    Animal* animals[] = {new Dog(), new Cat(), new SilentAnimal()};
    
    for (Animal* a : animals) {
        a->makeSound();  // Polymorphic call
    }
    
    for (Animal* a : animals) delete a;
    return 0;
}

ผลลัพธ์

Woof!
Meow!
Some generic animal sound

ตัวอย่าง Pure Virtual Function

#include <iostream>
#include <memory>

using namespace std;

class Shape {
public:
    // Pure virtual functions = Interface
    virtual double area() const = 0;
    virtual double perimeter() const = 0;
    virtual void draw() const = 0;
    
    // Virtual destructor สำคัญ!
    virtual ~Shape() = default;
    
    // Regular method ใช้ pure virtual functions
    void printInfo() const {
        cout << "Area: " << area() << ", Perimeter: " << perimeter() << endl;
    }
};

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    double area() const override { return 3.14159 * radius * radius; }
    double perimeter() const override { return 2 * 3.14159 * radius; }
    void draw() const override { cout << "Drawing circle (r=" << radius << ")\n"; }
};

class Rectangle : public Shape {
    double w, h;
public:
    Rectangle(double w_, double h_) : w(w_), h(h_) {}
    
    double area() const override { return w * h; }
    double perimeter() const override { return 2 * (w + h); }
    void draw() const override { cout << "Drawing rectangle (" << w << "x" << h << ")\n"; }
};

int main() {
    // Shape s;  // ❌ Error: abstract class
    
    unique_ptr<Shape> shapes[] = {
        make_unique<Circle>(5),
        make_unique<Rectangle>(4, 6)
    };
    
    for (auto& s : shapes) {
        s->draw();
        s->printInfo();
    }
    
    return 0;
}

ผลลัพธ์

Drawing circle (r=5)
Area: 78.5397, Perimeter: 31.4159
Drawing rectangle (4x6)
Area: 24, Perimeter: 20

Pure Virtual Function ที่มี Definition (Advanced)

Pure virtual function **สามารถมี definition ได้** (ยังคงเป็น pure virtual):

class Base {
public:
    virtual void cleanup() = 0;  // Pure virtual
};

// Definition แยกต่างหาก (ยังคงเป็น pure virtual)
void Base::cleanup() {
    cout << "Base cleanup logic\n";
}

class Derived : public Base {
public:
    void cleanup() override {
        Base::cleanup();  // เรียก base implementation ได้!
        cout << "Derived cleanup\n";
    }
};

เมื่อไหร่ควรใช้อะไร?

สถานการณ์แนะนำ
มี default behavior ที่สมเหตุสมผลRegular virtual function
ทุก derived class ต้อง implement เองPure virtual function
ต้องการสร้าง interface (contract)Pure virtual functions only
Base class ควรไม่ถูก instantiatePure virtual (ทำให้เป็น abstract)
ต้องการ common implementation + บังคับ overridePure virtual + provide definition

Abstract Class Design Guidelines

  1. **Interface classes**: มีแต่ pure virtual functions + virtual destructor
  2. **Abstract base classes**: มีทั้ง pure virtual และ regular virtual + data members
  3. **เสมอ**: virtual destructor (หรือ protected non-virtual destructor)
  4. **หลีกเลี่ยง**: เรียก virtual functions ใน constructor/destructor
  5. **ใช้**: override และ final (C++11)

สรุป

Virtual function = "นี่คือ default behavior แต่อนุญาตให้ override"
Pure virtual function = "นี่คือ contract ที่ derived class ต้อง implement เอง"
ทั้งคู่ร่วมกันสร้าง **Runtime Polymorphism** ใน C++