วิธีจัดระเบียบอินเทอร์เฟซและการนำไปใช้ใน C ++


12

ฉันได้เห็นว่ามีกระบวนทัศน์ที่แตกต่างกันใน C ++ เกี่ยวกับสิ่งที่จะเข้าไปในไฟล์ส่วนหัวและสิ่งที่จะ cpp ไฟล์ AFAIK ผู้คนส่วนใหญ่โดยเฉพาะผู้ที่อยู่ในพื้นหลัง C ทำ:

foo.h

 class foo {
 private:
     int mem;
     int bar();
 public:
     foo();
     foo(const foo&);
     foo& operator=(foo);
     ~foo();
 }

foo.cpp

 #include foo.h
 foo::bar() { return mem; }
 foo::foo() { mem = 42; }
 foo::foo(const foo& f) { mem = f.mem; }
 foo::operator=(foo f) { mem = f.mem; }
 foo::~foo() {}
 int main(int argc, char *argv[]) { foo f; }

อย่างไรก็ตามอาจารย์ของฉันมักสอน C ++ ให้กับผู้เริ่มต้นเช่นนี้:

foo.h

 class foo {
 private:
     int mem;
     int bar() { return mem; }
 public:
     foo() { mem = 42; }
     foo(const foo& f) { mem = f.mem; }
     foo& operator=(foo f) { mem = f.mem; }
     ~foo() {}
 }

foo.cpp

 #include foo.h
 int main(int argc, char* argv[]) { foo f; }
 // other global helper functions, DLL exports, and whatnot

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

ฉันต้องการรวบรวมมืออาชีพและแย้งด้วยวิธีใดวิธีหนึ่ง อาจจะมีวิธีอื่น ๆ อีกหรือ?

ข้อเสียอย่างหนึ่งในทางของฉันคือแน่นอนว่าต้องมีการประกาศล่วงหน้าเป็นครั้งคราว


2
foo.cppตอนนี้ไม่มีอะไรเกี่ยวข้องกับfooชั้นเรียนของคุณและควรปล่อยว่างไว้ (อาจเป็นเพราะ#includeระบบการสร้างของคุณมีความสุข)
Benjamin Bannier

2
อาจารย์ของคุณเสียสติ
การแข่งขัน Lightness ใน Orbit

คำตอบ:


16

ในขณะที่เวอร์ชันที่สองนั้นเขียนได้ง่ายกว่า

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

นอกจากนั้นคุณไม่ควรเปิดเผยรายละเอียดการใช้งานคุณจะได้รับการคอมไพล์ซ้ำโดยไม่จำเป็นกับเวอร์ชันที่สอง


1
+1 ผู้สร้างโปรไฟล์ของฉันไม่ได้วางโค้ดไว้ในไฟล์ส่วนหัวซึ่งเป็นเหตุผลที่มีค่าด้วย
ยูจีน

หากคุณเห็นคำตอบของฉันสำหรับคำถามนี้programmers.stackexchange.com/questions/4573/คุณจะเห็นว่ามันขึ้นอยู่กับความหมายของคลาสมากแค่ไหนเช่นจะใช้อะไร (โดยเฉพาะถ้ามันเป็นส่วนที่เปิดเผยของ อินเทอร์เฟซผู้ใช้ของคุณและจำนวนคลาสอื่น ๆ ในระบบของคุณใช้โดยตรง)
CashCow

3

ฉันทำอย่างที่สองในปี 93-95 ใช้เวลาไม่กี่นาทีในการคอมไพล์แอปเล็ก ๆ อีก 5-10 ฟังก์ชั่น / ไฟล์ (บนพีซี 486 เครื่องนั้น .. และไม่ฉันไม่รู้เกี่ยวกับชั้นเรียนฉันอายุแค่ 14-15 ปีและไม่มีอินเทอร์เน็ต ) .

ดังนั้นสิ่งที่คุณสอนผู้เริ่มต้นและสิ่งที่คุณใช้ในวิชาชีพเป็นเทคนิคที่แตกต่างกันอย่างมากมายโดยเฉพาะใน C ++

ฉันคิดว่าการเปรียบเทียบระหว่าง C ++ กับรถ F1 นั้นเหมาะเจาะ คุณไม่ได้ใส่ผู้เริ่มต้นในรถ F1 (ซึ่งไม่ได้เริ่มจนกว่าคุณจะอุ่นเครื่องยนต์ไว้ที่ 80-95 องศาเซลเซียส)

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


คำตอบนี้จะดียิ่งขึ้นถ้าคุณให้รายละเอียดเล็กน้อยเกี่ยวกับการรวบรวม / การเชื่อมโยงแบบคงที่ (ฉันไม่ทราบมาก่อน!)
Felix Dombek

2

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

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

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

เมื่อชั้นเรียนของคุณซับซ้อนมากขึ้นแม้จะเพิ่มการวนซ้ำข้อดีของการทำแบบนี้ก็จะแย่ลง

มันยังคงมีข้อดีอยู่โดยเฉพาะ:

  • หากนี่คือรหัส "ฟังก์ชันทั่วไป" คุณสามารถรวมส่วนหัวและใช้จากหลายโครงการโดยไม่ต้องเชื่อมโยงกับไลบรารีที่มีแหล่งที่มา

ข้อเสียของการ inline กลายเป็นปัญหาเมื่อมันหมายความว่าคุณจะต้องนำการใช้งานเฉพาะในส่วนหัวของคุณเช่นคุณต้องเริ่มต้นรวมถึงส่วนหัวพิเศษ

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


1

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

หากคุณกำลังตัดสินใจว่าจะเขียนไลบรารีเฉพาะส่วนหัวหัวข้อนี้เป็นเพียงหนึ่งในข้อกังวลของคุณ

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