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

ซ่อนการทำงานภายในด้วย PIMPL

ซ่อนรายละเอียดการทำงานภายในไว้เบื้องหลังสำนวนพอยน์เตอร์ไปยังการทำงานภายใน

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

สำนวน PIMPL

PIMPL = "ตัวชี้ไปยังการใช้งาน" ย้ายข้อมูลส่วนตัวของคลาสไปไว้ในโครงสร้าง impl แยกต่างหาก แล้วเข้าถึงผ่านตัวชี้

เหตุใดจึงใช้ PIMPL

ประโยชน์:

  • ซ่อนรายละเอียดการใช้งานจากส่วนหัว
  • ลดการพึ่งพาระหว่างการคอมไพล์
  • รักษาความเสถียรของ ABI เมื่อเพิ่มสมาชิกส่วนตัว
  • ทำให้สามารถสลับการใช้งานได้

โครงสร้างพื้นฐาน

คลาสสาธารณะเก็บตัวชี้ไปยังโครงสร้าง Impl ที่นิยามไว้เฉพาะในไฟล์ .cpp

// widget.h
class Widget {
public:
    Widget();
    ~Widget();
    void doSomething();
private:
    struct Impl;
    std::unique_ptr<Impl> pimpl_;
};

Impl ใน .cpp

โครงสร้าง Impl เก็บข้อมูลจริงทั้งหมด

// widget.cpp
struct Widget::Impl {
    std::string name;
    int counter;
    // ... anything else, freely
};

Widget::Widget()
    : pimpl_(std::make_unique<Impl>()) {}

Widget::~Widget() = default;  // must be in .cpp where Impl is complete

void Widget::doSomething() {
    pimpl_->counter++;
}

ตัวทำลายใน cpp

ต้องนิยามตัวทำลายในไฟล์ .cpp ซึ่ง Impl มีนิยามสมบูรณ์ มิฉะนั้น unique_ptr จะไม่สามารถลบชนิดข้อมูลที่มีนิยามไม่สมบูรณ์ได้

ฟังก์ชันสมาชิกพิเศษ

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

// widget.h
class Widget {
public:
    Widget(const Widget& other);
    Widget& operator=(const Widget& other);
    Widget(Widget&&) noexcept;
    Widget& operator=(Widget&&) noexcept;
    ~Widget();
};

ต้นทุนด้านประสิทธิภาพ

PIMPL เพิ่มการอ้างอิงทางอ้อมในการเข้าถึงสมาชิกทุกครั้ง และเพิ่มการจองหน่วยความจำบนฮีป สำหรับเมธอดที่เรียกบ่อย เรื่องนี้อาจมีผลได้ — โปรดวัดผลให้แน่ใจ

การสร้างที่เร็วขึ้น

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

PIMPL กับการสืบทอด

สามารถใช้ร่วมกับการสืบทอดได้ แต่จะเพิ่มความซับซ้อน โดยทั่วไปคลาสสาธารณะจะไม่สืบทอดจากสิ่งใด ส่วน Impl สามารถใช้การสืบทอดได้อย่างอิสระ

รูปแบบต่าง ๆ

ทางเลือกและการปรับปรุง:

  • Fast PIMPL — การเก็บข้อมูลแบบแทรกในหน่วยความจำด้วย new แบบระบุตำแหน่ง
  • Stable address — Impl ยังคงถูกจองหน่วยความจำไว้ตลอดอายุการใช้งานของออบเจ็กต์
  • Type erasure — Impl สามารถรองรับพหุรูปได้

การใช้งานจริง

PIMPL ถูกใช้อย่างแพร่หลายโดย:

  • Qt (ทุก Widget ใช้ PIMPL)
  • ไลบรารีกรรมสิทธิ์จำนวนมาก
  • Boost (ในบางส่วน)

ควรใช้เมื่อใด

ใช้ PIMPL เมื่อ:

  • คุณต้องการความเสถียรของ ABI ข้ามรุ่น
  • ส่วนหัวของคุณนำเข้าส่วนหัวอื่นต่อเนื่องมากเกินไป
  • คุณเปิดเผย API ของไลบรารีสาธารณะ

ควรข้ามเมื่อใด

ข้าม PIMPL เมื่อ:

  • คลาสเป็นส่วนภายใน ไม่มีผู้ใช้ใดพึ่งพาส่วนหัว
  • ค่าใช้จ่ายด้านประสิทธิภาพสำคัญกว่าเวลาการสร้าง
  • คลาสมีขนาดเล็กหรือไม่ค่อยมีการแก้ไข

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

เหตุใดตัวทำลายของคลาส PIMPL จึงต้องนิยามไว้ในไฟล์ .cpp

สรุป

PIMPL ซ่อนการใช้งานโดยย้ายข้อมูลส่วนตัวไปไว้ในโครงสร้าง Impl ที่เข้าถึงผ่าน unique_ptr ช่วยเพิ่มความเสถียรของ ABI และลดเวลาการสร้าง โดยแลกกับการอ้างอิงทางอ้อม โปรดนิยามฟังก์ชันสมาชิกพิเศษในไฟล์ .cpp ซึ่ง Impl มีนิยามสมบูรณ์

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

บทเรียน “ซ่อนการทำงานภายในด้วย PIMPL” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “ซ่อนการทำงานภายในด้วย PIMPL”

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

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

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

บทเรียน “ซ่อนการทำงานภายในด้วย PIMPL” ใช้เวลานานแค่ไหน

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

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

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

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

  1. ไลบรารีแบบมีเฉพาะส่วนหัวเทียบกับไลบรารีที่คอมไพล์แล้ว
  2. การกำหนดเวอร์ชัน API และความเสถียรของ ABI
  3. ซ่อนการทำงานภายในด้วย PIMPL
  4. การเขียนไลบรารียูทิลิตี C++ สมัยใหม่แบบมีเฉพาะส่วนหัว
← กลับไปที่ C++ Academy