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

Catch Block และ Type Conversion ใน C++: กฎการจับ Exception

ใน C++ Exception Handling, กฎการจับ Exception ด้วย catch Block มีความเข้มงวดกว่าการ Type Conversion ปกติ: ไม่มี Implicit Conversion ระหว่าง Thrown Object และ Catch Parameter (ยกเว้นบางกรณีเฉพาะ)

กฎสำคัญ

  1. No Standard Conversions: throw 'a'; catch(int) → ไม่จับได้ (Char ไป Int ไม่ได้)
  2. No User-Defined Conversions: Constructor Conversion, Conversion Operator ไม่ถูกใช้
  3. Derived → Base (Reference/Pointer): จับได้เฉพาะ Reference หรือ Pointer เท่านั้น (Polymorphism)
  4. Derived → Base (Value): เกิด Object Slicing (ตัดส่วน Derived ทิ้ง)
  5. catch(...): จับได้ทุกประเภท (Catch-all)

ตัวอย่าง 1: Char ไป Int ไม่ได้

try {
    throw 'a'; // char
}
catch (int a) {          // ไม่เข้ามา! ไม่มี char-to-int conversion ใน catch
    cout << "Caught int";
}
catch (...) {            // จับได้ที่นี่
    cout << "Default catch";
}
// Output: Default catch

ตัวอย่าง 2: Conversion Constructor ไม่ถูกเรียก

class Base {};
class Derived {
public:
    Derived(const Base&) { cout << "Conversion Ctor\n"; }
};

try {
    Base b;
    throw b; // Throw Base
}
catch (Derived d) { // ไม่เข้ามา! Conversion Constructor ไม่ถูกใช้
    cout << "Caught Derived";
}
catch (...) {
    cout << "Default catch";
}
// Output: Default catch

ตัวอย่าง 3: Polymorphic Catch (Reference) - ทำงานได้

class Base { virtual void foo() {} };
class Derived : public Base {};

try {
    Derived d;
    throw d;
}
catch (Base& b) { // จับได้! Reference Binding (No Slicing)
    cout << "Caught Base&";
}
// Output: Caught Base&

ลำดับความสำคัญของ Catch Blocks

Catch Blocks ถูกตรวจสอบ ตามลำดับที่เขียน ต้องวาง Derived Class ก่อน Base Class:

try { ... }
catch (Derived& d) { ... }  // ต้องอยู่ก่อน
catch (Base& b) { ... }     // Base มาต่อท้าย
catch (...) { ... }         // Catch-all ต้องท้ายสุด

Best Practices

  • Throw โดย Value, Catch โดย Const Reference: catch (const std::exception& e)
  • สร้าง Exception Hierarchy จาก std::exception
  • หลีกเลี่ยง Throw Primitive Types (int, char) ใช้ Class แทน
  • ใช้ std::current_exception / std::rethrow_exception สำหรับ Exception Propagation

สรุป

C++ Exception Matching ใช้ Exact Match หรือ Reference Binding To Base เท่านั้น ไม่มี Implicit Conversion ทำให้ Type Safety สูง แต่ต้องออกแบบ Exception Hierarchy และ Catch Order ให้ถูกต้อง