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

มิกซินด้วย CRTP

ประกอบพฤติกรรมขณะคอมไพล์

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

มิกซ์อินคืออะไร

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

มิกซ์อินอย่างง่าย

มิกซ์อินนี้เพิ่มฟังก์ชันสมาชิก print_twice ซึ่งต้องอาศัยคลาสเจ้าของที่มี value()

#include <iostream>

template <typename T>
struct PrintTwice {
    void print_twice() const {
        auto v = static_cast<const T*>(this)->value();
        std::cout << v << " " << v << "\n";
    }
};

struct Box : PrintTwice<Box> {
    int value() const { return 7; }
};

int main() {
    Box{}.print_twice();
    return 0;
}

การประกอบมิกซ์อินหลายรายการ

คุณสามารถสืบทอดจากมิกซ์อิน CRTP หลายรายการพร้อมกัน เพื่อซ้อนพฤติกรรมที่เป็นอิสระต่อกันไว้ในคลาสเดียว

#include <iostream>

template <typename T>
struct Loggable {
    void log() const { std::cout << "log: " << static_cast<const T*>(this)->id() << "\n"; }
};

template <typename T>
struct Resettable {
    void reset() { static_cast<T*>(this)->set(0); }
};

struct Device : Loggable<Device>, Resettable<Device> {
    int v = 5;
    int id() const { return v; }
    void set(int x) { v = x; }
};

int main() {
    Device d;
    d.log();
    d.reset();
    d.log();
    return 0;
}

มิกซ์อินเพิ่มสถานะได้เช่นกัน

มิกซ์อินสามารถมีสมาชิกข้อมูลของตนเอง ซึ่งจะกลายเป็นส่วนหนึ่งของโครงสร้างหน่วยความจำของออบเจ็กต์ที่ประกอบขึ้น

#include <iostream>

template <typename T>
struct Tagged {
    int tag = 0;
    void set_tag(int t) { tag = t; }
    int get_tag() const { return tag; }
};

struct Item : Tagged<Item> {
    const char* name = "item";
};

int main() {
    Item it;
    it.set_tag(42);
    std::cout << it.name << " " << it.get_tag() << "\n";
    return 0;
}

มิกซ์อินกับการสืบทอดทั่วไป

มิกซ์อิน CRTP แตกต่างจากการสืบทอดทั่วไป เพราะฐานสามารถเรียกย้อนลงไปยังคลาสสืบทอดได้ คลาสฐานทั่วไปไม่สามารถเรียกฟังก์ชันสมาชิกที่มีอยู่เฉพาะในประเภทสืบทอดได้ หากไม่มีฟังก์ชันเสมือน

การออกแบบตามนโยบาย

มิกซ์อินทำให้เกิดการออกแบบตามนโยบาย กล่าวคือเลือกพฤติกรรมขณะคอมไพล์ด้วยการเลือกว่าจะสืบทอดจากมิกซ์อินใด คล้ายกับที่ std::vector รับนโยบายตัวจัดสรร

ลำดับและโครงสร้างหน่วยความจำ

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

  • สร้างตามลำดับการประกาศฐาน
  • หลีกเลี่ยงมิกซ์อินที่ต้องพึ่งพากัน

การเพิ่มมิกซ์อินความเท่ากัน

ในตัวอย่างนี้ มิกซ์อินจะสร้าง operator!= จากการตรวจสอบความเท่ากันของคลาสเจ้าของ

#include <iostream>

template <typename T>
struct EqualityMixin {
    friend bool operator!=(const T& a, const T& b) { return !(a == b); }
};

struct P : EqualityMixin<P> {
    int x;
    P(int v) : x(v) {}
    friend bool operator==(const P& a, const P& b) { return a.x == b.x; }
};

int main() {
    std::cout << (P(1) != P(2)) << "\n";
    return 0;
}

มิกซ์อินแบบมีเงื่อนไข

คุณสามารถใส่มิกซ์อินเฉพาะเมื่อเงื่อนไขเป็นจริงได้ โดยผสานการสืบทอดเข้ากับ std::conditional เพื่อเลือกมิกซ์อินจริงหรือมิกซ์อินว่าง

การปรับให้ฐานว่างมีประสิทธิภาพ

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

#include <iostream>

template <typename T>
struct A {};
template <typename T>
struct B {};

struct C : A<C>, B<C> {
    int x;
};

int main() {
    std::cout << (sizeof(C) == sizeof(int)) << "\n";
    return 0;
}

ควรเลือกใช้มิกซ์อินเมื่อใด

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

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

ทดสอบความเข้าใจของคุณเกี่ยวกับมิกซ์อิน CRTP

สรุปทบทวน

คุณได้เรียนรู้การสร้างมิกซ์อินด้วย CRTP

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

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

บทเรียน “มิกซินด้วย CRTP” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “มิกซินด้วย CRTP”

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

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

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

บทเรียน “มิกซินด้วย CRTP” ใช้เวลานานแค่ไหน

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

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

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

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

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