ทำไมเราต้องใส่สมาชิกส่วนบุคคลไว้ในหัว?


62

ตัวแปรส่วนตัวเป็นวิธีการซ่อนความซับซ้อนและรายละเอียดการใช้งานให้กับผู้ใช้ของชั้นเรียน นี่เป็นฟีเจอร์ที่ค่อนข้างดี แต่ฉันไม่เข้าใจว่าทำไมใน c ++ เราต้องใส่ไว้ในส่วนหัวของชั้นเรียน ฉันเห็นข้อเสียที่น่ารำคาญสองประการนี้:

  • มันตัดส่วนหัวจากผู้ใช้
  • มันบังคับให้รวบรวมไคลเอนต์ไลบรารีทั้งหมดใหม่ทุกครั้งที่มีการแก้ไข internals

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


คุณสามารถประกาศ struct เปล่าในส่วนหัว แต่จากนั้นคุณสามารถใช้พอยน์เตอร์เพื่อ struct ดังกล่าวเมื่อคุณใช้มัน (และคุณไม่สามารถจัดสรรได้)
วงล้อประหลาด

3
@ratchetfreak: ไม่อนุญาตให้ว่างเปล่า ( struct foo{};) แต่เป็นการส่งต่อการประกาศ ( struct foo;)
MSalters

@MSalters นั่นคือสิ่งที่ฉันหมายถึง
วงล้อประหลาด

1
ให้ฉันเพิ่มข้อเสีย: * การเขียนส่วนหัวของฟังก์ชั่นส่วนตัวในไฟล์. h เป็นการเสียเวลาอย่างมาก (ลืมเรียนเพื่อนสักครู่)
Jonny

คำตอบ:


68

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

วิธีหนึ่งที่จะหลีกเลี่ยงปัญหานี้คือการใช้สำนวน Pimplอธิบายโดย Sutter สมุนไพรในคุรุของเขาของสัปดาห์ซีรีส์# 24และ# 28

ปรับปรุง

แท้จริงแล้วสิ่งนี้ (หรือมากกว่านั้นความแตกต่างของส่วนหัว / ซอร์สไฟล์และ#includes) เป็นอุปสรรค์สำคัญใน C ++ ที่สืบทอดมาจาก C. ย้อนกลับไปในวันที่C ++ C ถูกสร้างขึ้นไม่มีประสบการณ์กับการพัฒนาซอฟต์แวร์ขนาดใหญ่ เริ่มก่อให้เกิดปัญหาจริง บทเรียนที่ได้เรียนรู้ตั้งแต่นั้นเป็นต้นมาได้รับการเอาใจใส่จากนักออกแบบของภาษาใหม่ แต่ C ++ ถูกผูกมัดโดยข้อกำหนดด้านความเข้ากันได้แบบย้อนหลังทำให้ยากที่จะกล่าวถึงปัญหาพื้นฐานในภาษา


ข้อมูลประเภทนี้ไม่ได้มีอยู่ในห้องสมุดชั้นเรียนเท่านั้นหรือ มันใช้สำหรับการเชื่อมโยง?
Simon Bergot

@Simon คุณหมายถึงอะไรโดย "ห้องสมุดคลาส"?
PéterTörök

ฉันหมายถึงการรวบรวมไฟล์วัตถุที่มีคำจำกัดความและวิธีการเรียน
Simon Bergot

7
เมื่อ C ++ ถูกสร้างขึ้น AT & T / Bell Labs (นายจ้าง Stroustrups ในเวลานั้น) มีประสบการณ์กับการพัฒนา C ขนาดใหญ่อย่างแน่นอน ซอฟต์แวร์สวิตช์โทรศัพท์ 5ESS ของพวกเขาในเวลานั้นอาจเป็นโปรแกรม C ที่ใหญ่ที่สุดในโลก แนวคิดเบื้องต้นเกี่ยวกับ OO นั้นสามารถมองเห็นได้ในฐานรหัสนั้นและ Cfront ได้เลียนแบบเทคนิคเหล่านั้น อย่างไรก็ตามแนวคิดของprivateความทันสมัยมากขึ้น
MSalters

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

15

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

class X { 
    int a;
public:
    int b;
};

คอมไพเลอร์จะมักจะมีaที่ออฟเซต 0 และที่ออฟเซตb 4หากคอมไพเลอร์เห็นว่านี่เป็นเพียง:

class X { 
public:
    int b;
};

มันจะ "คิดว่า" ที่bควรจะชดเชย 0 แทนออฟเซ็ต 4 เมื่อรหัสโดยใช้คำนิยามที่กำหนดให้bรหัสโดยใช้คำนิยามแรกจะเห็นaได้รับการแก้ไขและในทางกลับกัน

วิธีปกติในการย่อเอฟเฟกต์ของการเปลี่ยนแปลงส่วนส่วนตัวของคลาสให้น้อยที่สุดมักเรียกว่า pimpl idiom (ซึ่งฉันมั่นใจว่า Google สามารถให้ข้อมูลได้มากมาย)


1
ฉันถามเกี่ยวกับการตัดสินใจออกแบบ แน่นอนว่าคุณต้องใส่ข้อความประกาศส่วนตัวของสมาชิกเพื่อให้ภาษาทำงานได้ แต่ทำไมมันควรอยู่ในส่วนหัวและไม่ได้อยู่ในสถานที่ที่เป็นส่วนตัวมากกว่านี้?
Simon Bergot

7
@Simon: ส่วนหัวคือคอมไพเลอร์ทั้งหมดเห็นเพื่อบอกว่าคลาส / struct ดูเหมือนอย่างไร มีการพูดคุยเกี่ยวกับการเพิ่มบางอย่างเช่นโมดูลไปยัง C ++ ซึ่งจะซ่อนข้อมูลประเภทนั้นอีกเล็กน้อย แต่จนถึงตอนนี้ก็ยังไม่ได้รับการอนุมัติ
Jerry Coffin

3
แต่ถึงกระนั้นกฎเล็ก ๆ น้อย ๆ ก็คือการจัดสรรสมาชิกส่วนตัวที่ ".cpp กำหนด" เช่นนี้ครั้งสุดท้าย นั่นหมายความว่าการชดเชยสาธารณะและสมาชิกส่วนตัว "ปกติ" จะไม่ขึ้นอยู่กับพวกเขา IMO เหตุผลที่แท้จริงคือคุณไม่สามารถสืบทอดจากชั้นเรียนดังกล่าวได้เนื่องจากส่วนที่ได้รับต้องติดตามแม้แต่สมาชิกส่วนตัวเหล่านั้น
MSalters

3

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

การคอมไพล์ไฟล์ที่ขึ้นต่อกันอาจขึ้นอยู่กับโครงสร้างการรวม การรวมไฟล์. h ในไฟล์. cpp แทนส่วนหัวอื่นสามารถทำได้ในบางกรณีป้องกันไม่ให้มีการคอมไพล์ยาว

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