สำนวน Pimpl เทียบกับอินเทอร์เฟซคลาสเสมือนจริง


118

ฉันสงสัยว่าอะไรจะทำให้โปรแกรมเมอร์เลือกสำนวน Pimpl หรือคลาสเสมือนจริงและการสืบทอด

ฉันเข้าใจว่าสำนวน pimpl มาพร้อมกับการกำหนดทิศทางพิเศษที่ชัดเจนสำหรับแต่ละวิธีสาธารณะและค่าใช้จ่ายในการสร้างวัตถุ

ในทางกลับกันคลาส Pure virtual มาพร้อมกับการกำหนดทิศทางโดยนัย (vtable) สำหรับการใช้งานที่สืบทอดมาและฉันเข้าใจว่าไม่มีค่าใช้จ่ายในการสร้างวัตถุ
แก้ไข : แต่คุณต้องมีโรงงานถ้าคุณสร้างวัตถุจากภายนอก

อะไรทำให้คลาสเสมือนจริงที่เป็นที่ต้องการน้อยกว่าสำนวน pimpl?


3
คำถามที่ดีเพียงแค่อยากจะถามในสิ่งเดียวกัน ดูboost.org/doc/libs/1_41_0/libs/smart_ptr/sp_techniques.html ด้วย
Frank

คำตอบ:


60

เมื่อเขียนคลาส C ++ ควรคิดว่าจะเป็นหรือไม่

  1. ประเภทค่า

    คัดลอกตามมูลค่าเอกลักษณ์ไม่สำคัญ มันเหมาะสมที่จะเป็นคีย์ใน std :: map ตัวอย่างคลาส "สตริง" หรือคลาส "วันที่" หรือคลาส "จำนวนเชิงซ้อน" ในการ "คัดลอก" อินสแตนซ์ของคลาสดังกล่าวเป็นเรื่องที่สมเหตุสมผล

  2. ประเภทเอนทิตี

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

ทั้ง pImpl และคลาสฐานนามธรรมล้วนเป็นเทคนิคในการลดการพึ่งพาเวลาในการคอมไพล์

อย่างไรก็ตามฉันเคยใช้ pImpl เพื่อใช้ Value types (type 1) เท่านั้นและบางครั้งก็ต่อเมื่อฉันต้องการลด coupling และ compile-time dependencies ให้น้อยที่สุด บ่อยครั้งมันไม่คุ้มค่ากับความรำคาญ ตามที่คุณชี้ให้เห็นอย่างถูกต้องมีค่าใช้จ่ายทางไวยากรณ์มากขึ้นเนื่องจากคุณต้องเขียนวิธีการส่งต่อสำหรับวิธีการสาธารณะทั้งหมด สำหรับคลาสประเภท 2 ฉันมักจะใช้คลาสพื้นฐานนามธรรมบริสุทธิ์กับวิธีการโรงงานที่เกี่ยวข้อง


6
โปรดดูความคิดเห็นของ Paul de Vrieze ต่อคำตอบนี้ Pimpl และ Pure Virtual แตกต่างกันอย่างมากหากคุณอยู่ในไลบรารีและต้องการสลับ. so / .dll โดยไม่ต้องสร้างไคลเอนต์ใหม่ ลูกค้าเชื่อมโยงไปยังส่วนหน้า pimpl ตามชื่อดังนั้นการรักษาลายเซ็นวิธีการแบบเก่าก็เพียงพอแล้ว OTOH ในกรณีนามธรรมบริสุทธิ์พวกเขาเชื่อมโยงอย่างมีประสิทธิภาพโดยดัชนี vtable ดังนั้นการเรียงลำดับวิธีการใหม่หรือการแทรกตรงกลางจะทำลายความเข้ากันได้
SnakE

1
คุณสามารถเพิ่ม (หรือสั่งซื้อใหม่) วิธีการในส่วนหน้าของคลาส Pimpl เท่านั้นเพื่อรักษาความสามารถในการเปรียบเทียบแบบไบนารี พูดตามเหตุผลคุณยังคงเปลี่ยนอินเทอร์เฟซและดูเหมือนว่าจะหลบไปเล็กน้อย คำตอบคือความสมดุลที่เหมาะสมซึ่งอาจช่วยในการทดสอบหน่วยโดยใช้ "การฉีดแบบพึ่งพา" แต่คำตอบนั้นขึ้นอยู่กับความต้องการเสมอ ผู้เขียนห้องสมุดบุคคลที่สาม (แตกต่างจากการใช้ห้องสมุดในองค์กรของคุณเอง) อาจชอบ Pimpl เป็นอย่างมาก
Spacen Jasset

31

Pointer to implementationมักจะเกี่ยวกับการซ่อนรายละเอียดการใช้งานโครงสร้าง Interfacesเกี่ยวกับการสร้างการใช้งานที่แตกต่างกัน พวกเขาตอบสนองวัตถุประสงค์สองประการที่แตกต่างกันจริงๆ


13
ไม่จำเป็นฉันเคยเห็นคลาสที่เก็บ pimpl หลายอันขึ้นอยู่กับการใช้งานที่ต้องการ บ่อยครั้งที่มีการกล่าวว่า win32 im เทียบกับ linux im ของบางสิ่งบางอย่างที่ต้องใช้งานแตกต่างกันไปในแต่ละแพลตฟอร์ม
Doug T.

14
แต่คุณสามารถใช้อินเทอร์เฟซเพื่อแยกรายละเอียดการใช้งานและซ่อนไว้ได้
Arkaitz Jimenez

6
แม้ว่าคุณจะใช้ pimpl โดยใช้อินเทอร์เฟซได้ แต่ก็ไม่มีเหตุผลที่จะแยกรายละเอียดการใช้งานออก ดังนั้นจึงไม่มีเหตุผลที่จะเปลี่ยนไป เหตุผลสำหรับ pimpl คือการเก็บรายละเอียดการดำเนินห่างจากลูกค้า (ใน C ++ เพื่อให้พวกเขาออกมาจากส่วนหัว) คุณอาจทำได้โดยใช้ฐาน / อินเทอร์เฟซที่เป็นนามธรรม แต่โดยทั่วไปแล้วจะเกินความจำเป็น
Michael Burr

10
ทำไมมันเกิน? ฉันหมายความว่าวิธีการเชื่อมต่อช้ากว่าวิธีการเชื่อมต่อหรือไม่? อาจมีเหตุผลเชิงตรรกะ แต่จากมุมมองในทางปฏิบัติฉันว่ามันง่ายกว่าที่จะทำด้วยอินเทอร์เฟซนามธรรม
Arkaitz Jimenez

1
ฉันจะบอกว่าคลาส / อินเทอร์เฟซพื้นฐานนามธรรมเป็นวิธี "ปกติ" ในการทำสิ่งต่างๆและช่วยให้การทดสอบง่ายขึ้นผ่านการล้อเลียน
Paulm

28

สำนวน pimpl ช่วยให้คุณลดการอ้างอิงและเวลาในการสร้างโดยเฉพาะอย่างยิ่งในแอปพลิเคชันขนาดใหญ่และลดการเปิดเผยส่วนหัวของรายละเอียดการใช้งานในชั้นเรียนของคุณให้เหลือเพียงหน่วยการรวบรวมเดียว ผู้ใช้ในชั้นเรียนของคุณไม่จำเป็นต้องตระหนักถึงการมีอยู่ของสิว (ยกเว้นเป็นตัวชี้ที่คลุมเครือซึ่งพวกเขาไม่ใช่องคมนตรี!)

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


17

ฉันกำลังค้นหาคำตอบสำหรับคำถามเดียวกัน หลังจากอ่านบทความและวิธีปฏิบัติบางอย่างแล้วฉันชอบใช้ "อินเทอร์เฟซคลาสเสมือนจริง"มากกว่า

  1. พวกเขาตรงไปตรงมามากขึ้น (นี่คือความคิดเห็นส่วนตัว) สำนวน Pimpl ทำให้ฉันรู้สึกว่าฉันกำลังเขียนโค้ด "สำหรับคอมไพเลอร์" ไม่ใช่สำหรับ "นักพัฒนาคนต่อไป" ที่จะอ่านโค้ดของฉัน
  2. กรอบการทดสอบบางอย่างมีการสนับสนุนโดยตรงสำหรับ Mocking คลาสเสมือนจริง
  3. เป็นเรื่องจริงที่คุณต้องมีโรงงานที่สามารถเข้าถึงได้จากภายนอก แต่ถ้าคุณต้องการใช้ประโยชน์จากความหลากหลาย: นั่นคือ "โปร" ด้วยไม่ใช่ "con" ... และวิธีโรงงานง่ายๆไม่เจ็บมาก

ข้อเสียเปรียบเพียงประการเดียว ( ฉันกำลังพยายามตรวจสอบเรื่องนี้ ) คือสำนวนของ pimpl อาจเร็วกว่า

  1. เมื่อการเรียกพร็อกซีอินไลน์ในขณะที่การสืบทอดจำเป็นต้องมีการเข้าถึงพิเศษไปยังวัตถุ VTABLE ที่รันไทม์
  2. รอยเท้าหน่วยความจำของ pimpl public-proxy-class มีขนาดเล็กลง (คุณสามารถทำการเพิ่มประสิทธิภาพได้อย่างง่ายดายเพื่อการแลกเปลี่ยนที่เร็วขึ้นและการเพิ่มประสิทธิภาพอื่น ๆ ที่คล้ายกัน)

21
โปรดจำไว้ว่าการใช้การสืบทอดคุณแนะนำการพึ่งพาเค้าโครง vtable ในการรักษา ABI คุณไม่สามารถเปลี่ยนฟังก์ชันเสมือนได้อีกต่อไป (การเพิ่มในตอนท้ายเป็นประเภทที่ปลอดภัยหากไม่มีคลาสย่อยที่เพิ่มเมธอดเสมือนของตนเอง)
Paul de Vrieze

1
^ ความคิดเห็นนี้ที่นี่ควรจะเหนียว
CodeAngry

10

ฉันเกลียดสิว! พวกเขาทำชั้นเรียนน่าเกลียดและอ่านไม่ออก วิธีการทั้งหมดจะเปลี่ยนเส้นทางไปที่สิว คุณไม่เคยเห็นในส่วนหัวว่ามีฟังก์ชันใดบ้างที่มีคลาสดังนั้นคุณจึงไม่สามารถปรับโครงสร้างใหม่ได้ (เช่นเพียงแค่เปลี่ยนการมองเห็นของวิธีการ) ดิชั้นรู้สึกเหมือน "ท้อง" ฉันคิดว่าการใช้ iterfaces นั้นดีกว่าและเพียงพอที่จะซ่อนการใช้งานจากไคลเอนต์ได้ คุณสามารถปล่อยให้ชั้นเรียนหนึ่งใช้อินเทอร์เฟซหลายอย่างเพื่อให้มีความบาง หนึ่งควรชอบอินเทอร์เฟซ! หมายเหตุ: คุณไม่จำเป็นต้องมีคลาสโรงงาน ที่เกี่ยวข้องคือคลาสไคลเอนต์สื่อสารกับอินสแตนซ์ผ่านอินเทอร์เฟซที่เหมาะสม การซ่อนวิธีการส่วนตัวฉันพบว่าเป็นความหวาดระแวงแปลก ๆ และไม่เห็นเหตุผลสำหรับสิ่งนี้เนื่องจากเรามีส่วนต่อประสาน


1
มีบางกรณีที่คุณไม่สามารถใช้อินเทอร์เฟซเสมือนจริงได้ ตัวอย่างเช่นเมื่อคุณมีรหัสเดิมและคุณมีโมดูลสองโมดูลที่คุณต้องแยกโดยไม่ต้องสัมผัส
AlexTheo

ดังที่ @Paul de Vrieze ชี้ให้เห็นด้านล่างคุณจะสูญเสียความเข้ากันได้ของ ABI เมื่อเปลี่ยนวิธีการของคลาสฐานเนื่องจากคุณมีการพึ่งพาโดยนัยกับ vtable ของคลาส ขึ้นอยู่กับกรณีการใช้งานว่าเป็นปัญหาหรือไม่
H. Rittich

"การซ่อนวิธีส่วนตัวที่ฉันพบว่าเป็นความหวาดระแวงแปลก ๆ " นั่นไม่อนุญาตให้คุณซ่อนการอ้างอิงและลดเวลาในการรวบรวมหากการอ้างอิงเปลี่ยนไปหรือไม่?
pooya13

ฉันยังไม่เข้าใจว่า Factories นั้นง่ายต่อการแยกตัวประกอบมากกว่า pImpl อย่างไร คุณไม่ออกจาก "อินเทอร์เฟซ" ทั้งสองกรณีและเปลี่ยนการใช้งานใช่หรือไม่ ในโรงงานคุณต้องแก้ไขไฟล์. h และ. cpp หนึ่งไฟล์และใน pImpl คุณต้องแก้ไขไฟล์. h และ. cpp หนึ่งไฟล์ แต่โดยทั่วไปแล้วคุณไม่จำเป็นต้องแก้ไขไฟล์ cpp ของอินเทอร์เฟซของ pImpl
pooya13

8

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

ในการอธิบายปัญหาโดยละเอียดให้พิจารณารหัสต่อไปนี้ในไลบรารี / ส่วนหัวที่ใช้ร่วมกันของคุณ:

// header
struct A
{
public:
  A();
  // more public interface, some of which uses the int below
private:
  int a;
};

// library 
A::A()
  : a(0)
{}

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

ในด้านของผู้ใช้รหัสที่เป็นnew Aครั้งแรกที่จะจัดสรรsizeof(A)ไบต์หน่วยความจำแล้วมือชี้ไปยังหน่วยความจำที่ให้กับตัวสร้างเป็นA::A()this

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

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

// header
struct A
{
public:
  A();
  // more public interface, all of which delegates to the impl
private:
  void * impl;
};

// library 
A::A()
  : impl(new A_impl())
{}

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

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


4
แทนที่จะเป็นโมฆะ * ฉันคิดว่ามันเป็นแบบดั้งเดิมมากกว่าที่จะประกาศคลาสการนำไปใช้:class A_impl *impl_;
Frank Krueger

9
ฉันไม่เข้าใจคุณไม่ควรประกาศสมาชิกส่วนตัวในชั้นเรียนเสมือนจริงที่คุณตั้งใจจะใช้เป็นอินเทอร์เฟซแนวคิดคือการรักษาชั้นเรียนให้เป็นนามธรรมไม่มีขนาดมีเพียงวิธีการเสมือนจริงเท่านั้นฉันไม่เห็นอะไรเลย คุณไม่สามารถทำผ่านไลบรารีที่แชร์ได้
Arkaitz Jimenez

@ Frank Krueger: คุณพูดถูกฉันขี้เกียจ @Arkaitz Jimenez: ความเข้าใจผิดเล็กน้อย; หากคุณมีคลาสที่มีเฉพาะฟังก์ชันเสมือนจริงก็ไม่มีประเด็นอะไรให้พูดถึงไลบรารีที่แชร์ ในทางกลับกันหากคุณกำลังจัดการกับไลบรารีที่ใช้ร่วมกันการอธิบายชั้นเรียนสาธารณะของคุณสามารถทำได้อย่างรอบคอบด้วยเหตุผลที่ระบุไว้ข้างต้น

10
สิ่งนี้ไม่ถูกต้อง ทั้งสองวิธีช่วยให้คุณสามารถซ่อนสถานะการนำไปใช้งานของชั้นเรียนของคุณได้หากคุณทำให้คลาสอื่นของคุณเป็นคลาส "ฐานนามธรรมบริสุทธิ์"
Paul Hollingsworth

10
ประโยคแรกใน anser ของคุณบ่งบอกว่าเวอร์ชวลที่แท้จริงด้วยวิธีการโรงงานที่เกี่ยวข้องไม่อนุญาตให้คุณซ่อนสถานะภายในของคลาส ที่ไม่เป็นความจริง. ทั้งสองเทคนิคช่วยให้คุณซ่อนสถานะภายในของคลาสได้ ความแตกต่างคือหน้าตาของผู้ใช้อย่างไร pImpl ช่วยให้คุณสามารถแสดงคลาสที่มีค่าความหมายได้ แต่ยังซ่อนสถานะภายใน วิธีโรงงาน Pure Abstract Base Class + ช่วยให้คุณแสดงประเภทเอนทิตีและยังช่วยให้คุณซ่อนสถานะภายในได้อีกด้วย อย่างหลังคือวิธีการทำงานของ COM บทที่ 1 ของ "Essential COM" มีข้อขัดข้องอย่างมากในเรื่องนี้
Paul Hollingsworth

6

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


3

แม้ว่าคำตอบอื่น ๆ จะกล่าวถึงในวงกว้าง แต่ฉันอาจจะอธิบายได้ชัดเจนกว่าเล็กน้อยเกี่ยวกับประโยชน์ของ pimpl ในคลาสฐานเสมือน:

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

// Pimpl
Object pi_obj(10);
std::cout << pi_obj.SomeFun1();

std::vector<Object> objs;
objs.emplace_back(3);
objs.emplace_back(4);
objs.emplace_back(5);
for (auto& o : objs)
    std::cout << o.SomeFun1();

// Abstract Base Class
auto abc_obj = ObjectABC::CreateObject(20);
std::cout << abc_obj->SomeFun1();

std::vector<std::shared_ptr<ObjectABC>> objs2;
objs2.push_back(ObjectABC::CreateObject(13));
objs2.push_back(ObjectABC::CreateObject(14));
objs2.push_back(ObjectABC::CreateObject(15));
for (auto& o : objs2)
    std::cout << o->SomeFun1();

2

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

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

แอปเปิ้ลและส้มจริงๆ


ฉันเห็นด้วยกับแอปเปิ้ล / ส้ม แต่ดูเหมือนว่าคุณใช้ pImpl สำหรับฟังก์ชัน เป้าหมายของฉันส่วนใหญ่คือการสร้างเทคนิคและการซ่อนข้อมูล
xtofl

2

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

โดยเฉพาะอย่างยิ่ง "เวลาสร้าง" เป็นปัญหาที่คุณสามารถแก้ไขได้โดยใช้ฮาร์ดแวร์ที่ดีกว่าหรือใช้เครื่องมือเช่น Incredibuild (www.incredibuild.com ซึ่งรวมอยู่ใน Visual Studio 2017 แล้วด้วย) จึงไม่ส่งผลต่อการออกแบบซอฟต์แวร์ของคุณ โดยทั่วไปการออกแบบซอฟต์แวร์ควรเป็นอิสระจากวิธีการสร้างซอฟต์แวร์


นอกจากนี้คุณยังชำระเงินด้วยเวลานักพัฒนาเมื่อเวลาสร้างคือ 20 นาทีแทนที่จะเป็น 2 ดังนั้นมันจึงสมดุลเล็กน้อยระบบโมดูลจริงจะช่วยได้มากที่นี่
Arkaitz Jimenez

IMHO วิธีการสร้างซอฟต์แวร์ไม่ควรมีผลต่อการออกแบบภายในเลย นี่เป็นปัญหาที่แตกต่างกันอย่างสิ้นเชิง
Trantor

2
อะไรทำให้ยากต่อการวิเคราะห์ การโทรจำนวนมากในไฟล์การใช้งานที่ส่งต่อไปยังคลาส Impl นั้นฟังดูไม่ยาก
mabraham

2
ลองนึกภาพการใช้งานการดีบักที่ใช้ทั้ง pimpl และ interface เริ่มต้นจากการโทรในรหัสผู้ใช้ A คุณติดตามไปที่อินเทอร์เฟซ B ข้ามไปที่คลาส C เพื่อเริ่มต้นการดีบักคลาสการใช้งาน D ... สี่ขั้นตอนจนกว่าคุณจะสามารถวิเคราะห์สิ่งที่เกิดขึ้นได้จริง และหากสิ่งทั้งหมดถูกนำไปใช้ใน DLL คุณจะพบอินเทอร์เฟซ C ที่ไหนสักแห่งในระหว่าง ...
Trantor

ทำไมคุณถึงใช้อินเทอร์เฟซกับ pImpl ในเมื่อ pImpl สามารถทำงานของอินเทอร์เฟซได้ (กล่าวคือสามารถช่วยให้คุณบรรลุการผกผันการพึ่งพา)
pooya13
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.