0Pricing
C++ Academy · บทเรียน

พหุรูปแบบแบบคงที่

หลีกเลี่ยงต้นทุนการเรียกเสมือน

พหุรูปแบบแบบคงที่ เป็นบทเรียน C++ Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C++ Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

พหุรูปแบบสองชนิด

C++ รองรับพหุรูปแบบสองลักษณะ

  • แบบไดนามิก: ฟังก์ชันเสมือนถูกแก้ไขขณะทำงานผ่านตารางเสมือน
  • แบบสแตติก: แม่แบบ/CRTP ถูกแก้ไขขณะคอมไพล์

พหุรูปแบบแบบสแตติกแลกความยืดหยุ่นกับความเร็ว

ต้นทุนของ virtual

การเรียกแบบเสมือนต้องกระโดดทางอ้อมผ่านตารางเสมือน โดยทั่วไปคอมไพเลอร์ไม่สามารถแทรกโค้ดการเรียกนี้ได้ ทำให้การปรับปรุงประสิทธิภาพหลายอย่างถูกขัดขวาง

#include <iostream>

struct Shape {
    virtual double area() const = 0;
    virtual ~Shape() = default;
};

struct Square : Shape {
    double s;
    Square(double x) : s(x) {}
    double area() const override { return s * s; }
};

int main() {
    Shape* p = new Square(3);
    std::cout << p->area() << "\n";
    delete p;
    return 0;
}

การเลือกเรียกแบบสแตติกด้วย CRTP

เมื่อใช้ CRTP คลาสพื้นฐานจะเรียกเมธอดของคลาสที่สืบทอดโดยตรงผ่านการแปลงชนิดขณะคอมไพล์ ดังนั้นคอมไพเลอร์จึงสามารถแทรกโค้ดทุกอย่างได้

#include <iostream>

template <typename T>
struct Shape {
    double area() const { return static_cast<const T*>(this)->area(); }
};

struct Square : Shape<Square> {
    double s;
    Square(double x) : s(x) {}
    double area() const { return s * s; }
};

int main() {
    Square sq(3);
    std::cout << sq.area() << "\n";
    return 0;
}

การตั้งชื่อฟังก์ชันส่งต่อ

เมื่อคลาสพื้นฐานและคลาสที่สืบทอดต่างก็กำหนด area ให้ตั้งชื่อฟังก์ชันส่งต่อของคลาสพื้นฐานให้แตกต่าง เช่น compute เพื่อให้เรียกไปยังการนำไปใช้ของคลาสที่สืบทอดได้อย่างไม่กำกวม

#include <iostream>

template <typename T>
struct Shape {
    double compute() const { return static_cast<const T*>(this)->area(); }
};

struct Circle : Shape<Circle> {
    double r;
    Circle(double x) : r(x) {}
    double area() const { return 3.14159 * r * r; }
};

int main() {
    Circle c(2);
    std::cout << c.compute() << "\n";
    return 0;
}

แม่แบบในฐานะพหุรูปแบบแบบสแตติก

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

#include <iostream>

struct Dog { void speak() const { std::cout << "Woof\n"; } };
struct Cat { void speak() const { std::cout << "Meow\n"; } };

template <typename Animal>
void make_speak(const Animal& a) { a.speak(); }

int main() {
    make_speak(Dog{});
    make_speak(Cat{});
    return 0;
}

เมื่อทราบประเภท

พหุสัณฐานแบบคงที่ใช้ได้เฉพาะเมื่อทราบประเภทจริงขณะคอมไพล์ หากต้องเก็บออบเจ็กต์ต่างประเภทไว้ในโครงสร้างเก็บข้อมูลเดียวกันและเลือกพฤติกรรมขณะทำงาน คุณยังคงต้องใช้ฟังก์ชันเสมือน

ไม่มีโครงสร้างเก็บข้อมูลต่างประเภท

คุณไม่สามารถใส่ Shape<Square> และ Shape<Circle> ไว้ใน std::vector เดียวกันโดยใช้เป็นฐานร่วมได้ เพราะทั้งสองเป็นประเภทที่ไม่เกี่ยวข้องกัน นี่คือข้อจำกัดสำคัญของพหุสัณฐานแบบคงที่

ประโยชน์ด้านประสิทธิภาพ

เมื่อแทรกการเรียกที่เลือกไว้ลงในโค้ดโดยตรง คอมไพเลอร์สามารถรวมค่าคงที่และกำจัดค่าใช้จ่ายของการเรียกฟังก์ชันได้ทั้งหมด ในลูปที่ทำงานซ้ำอย่างเข้มข้นกับประเภทเดียวที่ทราบแน่ชัด พหุสัณฐานแบบคงที่อาจทำงานได้เร็วขึ้นอย่างมาก

#include <iostream>

template <typename T>
struct Op {
    int apply(int x) const { return static_cast<const T*>(this)->apply(x); }
};

struct Doubler : Op<Doubler> {
    int apply(int x) const { return x * 2; }
};

int main() {
    Doubler d;
    int sum = 0;
    for (int i = 0; i < 5; ++i) sum += d.apply(i);
    std::cout << sum << "\n";
    return 0;
}

การใช้ทั้งสองแบบร่วมกัน

คุณสามารถใช้ CRTP สำหรับเส้นทางการทำงานหลัก และใช้ตัวห่อหุ้มฟังก์ชันเสมือนขนาดเล็กเมื่อจำเป็นต้องลบข้อมูลประเภท วิธีนี้ให้ความเร็วในจุดที่สำคัญ และให้ความยืดหยุ่นเมื่อจำเป็น

การตรวจสอบส่วนติดต่อแบบคงที่

หากคลาสสืบทอดลืมใช้งานฟังก์ชันสมาชิกที่จำเป็น ข้อผิดพลาดจะแสดงขึ้นขณะคอมไพล์เมื่อมีการสร้างอินสแตนซ์ของตัวส่งต่อจากฐาน ไม่ใช่ขณะทำงาน

#include <iostream>

template <typename T>
struct Greeter {
    void greet() const { static_cast<const T*>(this)->hello(); }
};

struct English : Greeter<English> {
    void hello() const { std::cout << "Hello\n"; }
};

int main() {
    English{}.greet();
    return 0;
}

การเลือกเครื่องมือที่เหมาะสม

ใช้พหุสัณฐานแบบคงที่เมื่อ:

  • ทราบประเภทขณะคอมไพล์
  • ประสิทธิภาพมีความสำคัญอย่างยิ่ง
  • ไม่จำเป็นต้องมีประเภทฐานร่วมขณะทำงาน

มิฉะนั้น ควรเลือกใช้ฟังก์ชันเสมือนเพื่อให้โค้ดเข้าใจง่ายและยืดหยุ่น

ตรวจสอบความเข้าใจ

เลือกข้อแลกเปลี่ยนสำคัญของพหุสัณฐานแบบคงที่

สรุปทบทวน

คุณได้เปรียบเทียบพหุสัณฐานแบบคงที่และแบบพลวัต

  • ฟังก์ชันเสมือน = การเลือกเรียกขณะทำงาน ตารางฟังก์ชันเสมือน และโครงสร้างเก็บข้อมูลต่างประเภท
  • CRTP/แม่แบบ = การเลือกเรียกขณะคอมไพ��� สามารถแทรกโค้ดได้ และทำงานเร็วกว่า
  • แบบคงที่ต้องทราบประเภทขณะคอมไพล์
  • เลือกใช้โดยพิจารณาความต้องการด้านความยืดหยุ่นเทียบกับประสิทธิภาพ

คำถามที่พบบ่อย

บทเรียน “พหุรูปแบบแบบคงที่” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “พหุรูปแบบแบบคงที่” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C++ Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C++ Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “พหุรูปแบบแบบคงที่”

หลีกเลี่ยงต้นทุนการเรียกเสมือน คุณปฏิบัติ C++ Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C++ Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C++ Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “พหุรูปแบบแบบคงที่” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C++ Academy นี้ได้ไหม

ได้ บทเรียน C++ Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. สำนวน CRTP
  2. พหุรูปแบบแบบคงที่
  3. มิกซินด้วย CRTP
  4. เมื่อใดควรใช้ CRTP
← กลับไปที่ C++ Academy