เหตุใด C ++ จึงไม่มีการสะท้อน


337

นี่เป็นคำถามที่ค่อนข้างแปลกประหลาด วัตถุประสงค์ของฉันคือเข้าใจการตัดสินใจออกแบบภาษาและระบุความเป็นไปได้ของการสะท้อนใน C ++

  1. ทำไมคณะกรรมการภาษา C ++ ไม่สามารถนำการสะท้อนกลับมาใช้ในภาษาได้? การสะท้อนกลับยากเกินไปในภาษาที่ไม่ได้ทำงานบนเครื่องเสมือน (เช่น java) หรือไม่?

  2. หากมีการใช้การสะท้อนกลับสำหรับ C ++ สิ่งที่จะเป็นความท้าทาย?

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

คำตอบ:


631

มีปัญหาหลายอย่างกับการสะท้อนใน C ++

  • มันเป็นงานที่ต้องเพิ่มอีกมากและคณะกรรมการ C ++ นั้นค่อนข้างอนุรักษ์นิยมและไม่ต้องใช้เวลากับคุณสมบัติใหม่ที่ต่างไปจากเดิมเว้นแต่ว่าพวกเขาจะแน่ใจ (ข้อเสนอแนะสำหรับการเพิ่มระบบโมดูลที่คล้ายกับแอสเซมบลี. NET ได้รับการทำและในขณะที่ฉันคิดว่ามีฉันทามติทั่วไปว่ามันจะดีที่จะมีมันไม่ใช่ลำดับความสำคัญสูงสุดของพวกเขาในขณะนี้และได้รับการผลักดัน C ++ 0x แรงจูงใจสำหรับคุณลักษณะนี้คือการกำจัด#includeระบบ แต่ก็จะเปิดใช้งานเมตาดาต้าอย่างน้อยบางส่วน)

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

  • ซึ่งนำเราไปสู่อีกจุดใหญ่: C ++ ทำให้การรับประกันน้อยมากเกี่ยวกับรหัสที่รวบรวม คอมไพเลอร์ได้รับอนุญาตให้ทำทุกอย่างที่มันชอบตราบใดที่ฟังก์ชั่นที่ได้นั้นเป็นสิ่งที่คาดหวัง ตัวอย่างเช่นชั้นเรียนของคุณไม่จำเป็นต้อง อยู่ที่นั่นจริงๆ คอมไพเลอร์สามารถเพิ่มประสิทธิภาพพวกเขาออกไปแทรกทุกสิ่งที่พวกเขาทำและมันก็ทำอย่างนั้นบ่อย ๆ เพราะแม้แต่รหัสเทมเพลตที่เรียบง่ายก็มีแนวโน้มที่จะสร้างอินสแตนซ์ของแม่แบบที่ค่อนข้างน้อย ไลบรารีมาตรฐาน C ++ อาศัยการเพิ่มประสิทธิภาพเชิงรุกนี้ Functors เป็นนักแสดงเฉพาะในกรณีที่ค่าโสหุ้ยในการสร้างอินสแตนซ์และการทำลายล้างวัตถุสามารถปรับให้เหมาะสม operator[]บนเวกเตอร์นั้นสามารถเทียบเคียงได้กับการจัดทำดัชนีอาเรย์ดิบในการดำเนินการเพราะผู้ประกอบการทั้งหมดสามารถถูกแทรกและลบออกจากโค้ดที่คอมไพล์ทั้งหมด C # และ Java รับประกันจำนวนมากเกี่ยวกับผลลัพธ์ของคอมไพเลอร์ ถ้าฉันกำหนดคลาสใน C # คลาสนั้นจะมีอยู่ในแอสเซมบลีที่เป็นผลลัพธ์ แม้ว่าฉันจะไม่เคยใช้ แม้ว่าการเรียกฟังก์ชั่นสมาชิกทั้งหมดจะสามารถถูกขีดเส้นใต้ได้ ชั้นต้องอยู่ที่นั่นเพื่อให้การสะท้อนนั้นสามารถพบได้ ส่วนหนึ่งของสิ่งนี้คือการบรรเทาโดยการรวบรวม C # เพื่อ bytecode ซึ่งหมายความว่าคอมไพเลอร์ JIT สามารถลบนิยามคลาสและฟังก์ชั่นอินไลน์หากชอบแม้ว่าคอมไพเลอร์เริ่มต้น C # จะไม่สามารถทำได้ ใน C ++ คุณมีคอมไพเลอร์เพียงตัวเดียวและมันจะมีโค้ดที่มีประสิทธิภาพ หากคุณได้รับอนุญาตให้ตรวจสอบข้อมูลเมตาของ C ++ ที่ปฏิบัติการได้คุณคาดว่าจะเห็นทุกคลาสที่กำหนดไว้ซึ่งหมายความว่าคอมไพเลอร์จะต้องรักษาคลาสที่กำหนดไว้ทั้งหมดแม้ว่าจะไม่จำเป็นก็ตาม

  • แล้วมีแม่แบบ เทมเพลตใน C ++ นั้นไม่เหมือนกับภาษาอังกฤษทั่วไป ทุกการสร้างแม่แบบสร้าง ประเภทใหม่ เป็นชั้นที่แยกจากกันอย่างสมบูรณ์จากstd::vector<int> std::vector<float>ซึ่งเพิ่มประเภทต่าง ๆ มากมายในโปรแกรมทั้งหมด สิ่งที่สะท้อนของเราควรเห็น แม่แบบ std::vector ? แต่จะทำได้อย่างไรเนื่องจากเป็นซอร์สโค้ดที่ไม่มีความหมายในขณะรันไทม์ มันจะต้องดูแยกชั้นเรียน และstd::vector<int> std::vector<float>และ std::vector<int>::iteratorและ std::vector<float>::iteratorสำหรับเดียวกันconst_iteratorและอื่น ๆ และเมื่อคุณก้าวเข้าสู่การเขียนโปรแกรมแม่แบบแม่แบบคุณจะสิ้นสุดการสร้างอินสแตนซ์ของเทมเพลตนับร้อยได้อย่างรวดเร็วซึ่งทั้งหมดจะได้รับการอินไลน์และลบออกอีกครั้งโดยคอมไพเลอร์ ไม่มีความหมายยกเว้นเป็นส่วนหนึ่งของ metaprogram เวลาคอมไพล์ ควรจะสะท้อนให้เห็นชั้นเรียนเหล่านี้หลายร้อยชั้นหรือไม่ พวกเขาจะต้องเพราะมิฉะนั้นการสะท้อนของเราจะไร้ประโยชน์ถ้ามันไม่ไม่ได้รับประกันว่าการเรียนที่ผมกำหนดไว้จริงจะอยู่ที่นั่น และปัญหาด้านคือคลาสเทมเพลตไม่มีอยู่จนกว่าจะสร้างอินสแตนซ์ std::vector<int>ลองนึกภาพโปรแกรมที่ใช้ ระบบการสะท้อนของเราควรจะเห็นได้std::vector<int>::iteratorหรือไม่? ในมือข้างหนึ่งคุณคาดหวังไว้อย่างแน่นอน มันเป็นคลาสที่สำคัญและถูกกำหนดในแง่ของstd::vector<int>ซึ่งทำมีอยู่ในเมตาดาต้า ในทางกลับกันถ้าโปรแกรมไม่เคยใช้เทมเพลตคลาสตัววนซ้ำนี้จริงชนิดของมันจะไม่ถูกทำให้เป็นอินสแตนซ์ดังนั้นคอมไพเลอร์จะไม่สร้างคลาสในตอนแรก และมันก็สายเกินไปที่จะสร้างมันตอนรันไทม์เนื่องจากมันต้องการการเข้าถึงซอร์สโค้ด

  • และสุดท้ายการไตร่ตรองก็ไม่สำคัญเท่า C ++ เหมือนใน C # เหตุผลก็คืออีกครั้งเทมเพลตการวางแผนโปรแกรม มันไม่สามารถแก้ปัญหาทุกอย่างได้ แต่สำหรับหลาย ๆ กรณีที่คุณใช้วิธีไตร่ตรองเป็นอย่างอื่นคุณสามารถเขียน metaprogram boost::type_traitsเป็นตัวอย่างง่ายๆ คุณต้องการที่จะรู้เกี่ยวกับประเภท T? type_traitsตรวจสอบของ ใน C # คุณจะต้องตกปลาตามชนิดของมันโดยใช้การสะท้อน การสะท้อนจะยังคงมีประโยชน์สำหรับบางสิ่ง (การใช้งานหลักที่ฉันเห็นซึ่ง metaprogramming ไม่สามารถแทนที่ได้อย่างง่ายดายคือสำหรับรหัสการทำให้เป็นอนุกรมที่สร้างอัตโนมัติ) แต่มันจะมีค่าใช้จ่ายที่สำคัญบางอย่างสำหรับ C ++ และมันไม่จำเป็นบ่อยเท่า อยู่ในภาษาอื่น ๆ

แก้ไข: เพื่อตอบสนองต่อความคิดเห็น:

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

Evan Teran: แน่นอนปัญหาเหล่านี้สามารถแก้ไขได้ แต่นั่นกลับไปยังจุดที่ # 1 ของฉัน มันต้องใช้เวลามากและคณะกรรมการ C ++ มีหลายสิ่งที่พวกเขารู้สึกว่ามีความสำคัญมากกว่า ประโยชน์ของการได้รับการสะท้อน จำกัด (และมันจะถูก จำกัด ) ใน C ++ มีขนาดใหญ่พอที่จะแสดงให้เห็นถึงการมุ่งเน้นที่ค่าใช้จ่ายของคุณสมบัติอื่น ๆ ? มีประโยชน์อย่างมากในการเพิ่มฟีเจอร์ภาษาหลักที่สามารถทำได้ (ส่วนใหญ่) ผ่านไลบรารี่และตัวประมวลผลล่วงหน้าอย่าง QT หรือไม่? บางที แต่ความต้องการนั้นเร่งด่วนน้อยกว่าห้องสมุดที่ไม่มีอยู่จริง สำหรับคำแนะนำเฉพาะของคุณฉันเชื่อว่าการไม่อนุญาตให้ใช้กับเทมเพลตจะทำให้ไร้ประโยชน์อย่างสมบูรณ์ ตัวอย่างเช่นคุณไม่สามารถใช้การสะท้อนกลับในไลบรารีมาตรฐานได้ การไตร่ตรองแบบไหนstd::vector? เทมเพลตเป็นส่วนใหญ่ของ C ++ คุณลักษณะที่ไม่สามารถใช้งานกับแม่แบบนั้นไม่มีประโยชน์

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

แต่อย่างที่ฉันพูดมีข้อเสนอสำหรับการเปลี่ยนแปลงรูปแบบการคอมไพล์เพิ่มโมดูลที่มีอยู่ในตัวเองเก็บเมตาดาต้าสำหรับประเภทที่เลือกไว้ทำให้โมดูลอื่น ๆ สามารถอ้างอิงได้โดยไม่ต้องยุ่งกับ#includes นั่นเป็นการเริ่มต้นที่ดีและพูดตามตรงฉันประหลาดใจที่คณะกรรมการมาตรฐานไม่เพียง แต่ทิ้งข้อเสนอไว้เพราะการเปลี่ยนแปลงครั้งใหญ่เกินไป ดังนั้นบางทีใน 5-10 ปี? :)


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

2
อีกอย่างเกี่ยวกับประเด็นแรกของคุณ: เท่าที่ฉันรู้ว่าไม่มีใครลองเพิ่มการสะท้อนไปยังการใช้งาน C ++ ไม่มีประสบการณ์ที่ดีกับมัน คณะกรรมการอาจจะไม่เต็มใจที่จะนำเฉพาะอย่างยิ่งหลังจากและexport vector<bool>
David Thornley

18
ฉันยอมรับว่า C ++ ไม่ควรมีการสะท้อนเวลา แต่การรวบรวมเวลาสะท้อนมีปัญหาข้างต้นน้อยและสามารถนำมาใช้สำหรับใครบางคนในการสร้างการสะท้อนเวลาทำงานในชั้นเรียนเฉพาะถ้าพวกเขาเลือกที่จะ ความสามารถในการเข้าถึงประเภทและชื่อและคุณสมบัติของวิธีการที่ n และผู้ปกครองที่ n ของชั้นเรียนผ่านแม่แบบหรือไม่? และรับจำนวนดังกล่าวในเวลารวบรวม? จะทำให้การสะท้อนภาพอัตโนมัติ CRTP ทำงานได้ในขณะที่ไม่มีใครจ่ายเงินสำหรับสิ่งที่พวกเขาไม่ได้ใช้
Yakk - Adam Nevraumont

15
ประเด็นที่สามของคุณมีความสำคัญหลายประการ: C ++ นั้นเหมาะสำหรับการเขียนโค้ดแบบสแตนด์อโลนบนแพลตฟอร์มที่หน่วยความจำมีค่าใช้จ่าย หากการกำจัดรหัสที่ไม่ได้ใช้จะทำให้โปรแกรมสามารถบรรจุไมโครคอนโทรลเลอร์ที่มีราคา 2.00 ดอลลาร์แทนที่จะเป็นหนึ่งที่มีราคา 2.50 ดอลลาร์และหากรหัสมีจำนวน 1,000,000 หน่วยการกำจัดรหัสนั้นสามารถประหยัดได้ 500,000 ดอลลาร์ การวิเคราะห์แบบคงที่สามารถระบุรหัส 90% + ที่ไม่สามารถเข้าถึงได้ หากอนุญาตให้มีการสะท้อนแสงสิ่งใดก็ตามที่สามารถเข้าถึงได้ผ่านทาง Reflection นั้นจะต้องสามารถเข้าถึงได้แม้ว่าจะไม่ใช่ 90% ก็ตาม
supercat

2
มีแน่นอนบางสิ่งบางอย่างที่สามารถปรับปรุงได้อย่างง่ายดายโดย comitee มันเป็นไปจนบอกว่าสีดำบนสีขาวที่typeinfoเป็นname()ฟังก์ชั่นจะต้องกลับชื่อที่ได้รับการพิมพ์ในโดยโปรแกรมเมอร์และไม่ได้บางสิ่งบางอย่างไม่ได้กำหนด และให้ stringifier แก่เราเช่นกัน สิ่งนี้สำคัญมากสำหรับการทำให้เป็นอนุกรม / การดีซีเรียล
ไลซ์เซชัน

38

Reflection ต้องการข้อมูลเมตาเกี่ยวกับประเภทที่จะเก็บไว้ที่ไหนสักแห่งที่สามารถสอบถามได้ เนื่องจาก C ++ คอมไพล์กับรหัสเครื่องดั้งเดิมและผ่านการเปลี่ยนแปลงอย่างมากเนื่องจากการปรับให้เหมาะสมมุมมองระดับสูงของแอปพลิเคชันจะหายไปในกระบวนการรวบรวมดังนั้นจึงไม่สามารถสืบค้นได้ในเวลาทำงาน Java และ. NET ใช้การแทนค่าระดับสูงมากในรหัสเลขฐานสองสำหรับเครื่องเสมือนทำให้ระดับการสะท้อนนี้เป็นไปได้ อย่างไรก็ตามในการประยุกต์ใช้ C ++ บางอย่างมีบางสิ่งที่เรียกว่า Run Time Type Information (RTTI) ซึ่งถือได้ว่าเป็นภาพสะท้อนที่มีการถอดแบบ


15
RTTI อยู่ในมาตรฐาน C ++
Daniel Earwicker

1
แต่การใช้งาน C ++ ทั้งหมดนั้นไม่ใช่มาตรฐาน ฉันเห็นการใช้งานที่ไม่สนับสนุน RTTI
Mehrdad Afshari

3
และการใช้งานส่วนใหญ่ที่สนับสนุน RTTI ยังสนับสนุนการปิดตัวเลือกผ่านตัวรวบรวม
Michael Kohne

21

ทุกภาษาไม่ควรพยายามรวมคุณสมบัติทุกอย่างของภาษาอื่น ๆ

C ++ นั้นเป็นแอสเซมเบลอร์แมโครที่ซับซ้อนมาก มันไม่ใช่ (ในแง่ดั้งเดิม) ภาษาระดับสูงเช่น C #, Java, Objective-C, Smalltalk เป็นต้น

เป็นการดีที่มีเครื่องมือต่าง ๆ สำหรับงานที่แตกต่างกัน ถ้าเรามีค้อนเท่านั้นทุกอย่างจะมีลักษณะเหมือนตะปู ฯลฯ การมีภาษาสคริปต์มีประโยชน์สำหรับงานบางงานและภาษา OO แบบไตร่ตรอง (Java, Obj-C, C #) มีประโยชน์สำหรับงานประเภทอื่นและสุดยอด ภาษาเปลือยใกล้กับเครื่องที่มีประสิทธิภาพมีประโยชน์สำหรับงานประเภทอื่น (C ++, C, Assembler)

C ++ เป็นงานที่น่าทึ่งในการขยายเทคโนโลยี Assembler ไปสู่การจัดการความซับซ้อนในระดับที่น่าเหลือเชื่อและนามธรรมเพื่อทำให้การเขียนโปรแกรมมีขนาดใหญ่ขึ้นและมีความซับซ้อนมากยิ่งขึ้นสำหรับมนุษย์ แต่ไม่จำเป็นต้องเป็นภาษาที่เหมาะสมที่สุดสำหรับผู้ที่กำลังใกล้ถึงปัญหาจากมุมมองระดับสูงอย่างเข้มงวด (Lisp, Smalltalk, Java, C #) หากคุณต้องการภาษาที่มีคุณสมบัติเหล่านั้นเพื่อใช้การแก้ปัญหาของคุณให้ดีที่สุดขอขอบคุณผู้ที่ได้สร้างภาษาดังกล่าวเพื่อให้พวกเราทุกคนใช้!

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

C #, Java, Objective-C ทั้งหมดต้องการระบบรันไทม์ที่ใหญ่กว่าและสมบูรณ์ยิ่งขึ้นเพื่อรองรับการทำงานของมัน จะต้องส่งมอบรันไทม์นั้นให้กับระบบที่มีปัญหา - ติดตั้งล่วงหน้าเพื่อรองรับการทำงานของซอฟต์แวร์ของคุณ และเลเยอร์นั้นจะต้องได้รับการบำรุงรักษาสำหรับระบบเป้าหมายต่าง ๆ ปรับแต่งโดย SANG OTHER LANGUAGE เพื่อให้มันทำงานบนแพลตฟอร์มนั้น และเลเยอร์กลางนั้น - เลเยอร์ที่ปรับได้ระหว่างโฮสต์ระบบและโค้ดของคุณ - รันไทม์นั้นเกือบจะเขียนด้วยภาษาเช่น C หรือ C ++ ซึ่งมีประสิทธิภาพเป็นอันดับที่ 1 ซึ่งการทำความเข้าใจการคาดการณ์ที่แม่นยำระหว่างการทำงานร่วมกันระหว่างซอฟต์แวร์และฮาร์ดแวร์ เข้าใจและจัดการเพื่อให้ได้ประโยชน์สูงสุด

ฉันชอบ Smalltalk, Objective-C และมีระบบรันไทม์ที่สมบูรณ์พร้อมการสะท้อน meta-data การรวบรวมขยะ ฯลฯ สามารถเขียนโค้ดที่น่าอัศจรรย์เพื่อใช้ประโยชน์จากสิ่งอำนวยความสะดวกเหล่านี้! แต่นั่นเป็นเพียงเลเยอร์ที่สูงกว่าบนสแต็กซึ่งเป็นเลเยอร์ที่ต้องพักบนเลเยอร์ที่ต่ำกว่าซึ่งท้ายที่สุดแล้วพวกเขาจะต้องนั่งบนระบบปฏิบัติการและฮาร์ดแวร์ และเราจะต้องใช้ภาษาที่เหมาะสมที่สุดสำหรับการสร้างเลเยอร์นั้น: C ++ / C / Assembler

ภาคผนวก: C ++ 11/14 ยังคงขยายขีดความสามารถ C ++ ต่อไปเพื่อรองรับ abstractions และระบบระดับสูงขึ้น เธรดการซิงโครไนซ์โมเดลหน่วยความจำที่แม่นยำและคำจำกัดความของเครื่องนามธรรมที่แม่นยำยิ่งขึ้นทำให้นักพัฒนา C ++ สามารถบรรลุ abstractions ระดับสูงซึ่งภาษาระดับสูงเหล่านี้บางภาษาเท่านั้นที่ใช้ในการมีโดเมนเอกสิทธิ์เฉพาะในขณะเดียวกัน ประสิทธิภาพของโลหะและการคาดการณ์ที่ยอดเยี่ยม (เช่นระบบย่อยรันไทม์น้อยที่สุด) บางทีสิ่งอำนวยความสะดวกในการไตร่ตรองอาจถูกเลือกให้เปิดใช้งานในการปรับปรุง C ++ ในอนาคตสำหรับผู้ที่ต้องการ - หรืออาจเป็นห้องสมุดที่จะให้บริการรันไทม์เช่นนั้น (อาจมีอยู่ตอนนี้หรือตอนเริ่มต้นด้วยการเพิ่ม)


ประเด็นของคุณเกี่ยวกับการรันไทม์ของภาษาที่ต้องรวบรวมในภาษาอื่นนั้นไม่เป็นความจริงในกรณีของ Objective-C เนื่องจากรันไทม์ของมันเขียนด้วยภาษา C (ซึ่ง Objective-C เป็นชุดของ)
Richard J. Ross III

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

3
ฉันขอโทษ; แต่ตราบใดที่คุณเชื่อมโยงอย่างถูกต้องคุณสามารถรวบรวมโปรแกรมวัตถุประสงค์ -c ใน C ในความเป็นจริงฉันไม่ได้ที่นี่: stackoverflow.com/a/10290255/427309 ข้อความข้างต้นทั้งหมดของคุณเป็นเท็จ รันไทม์สามารถเข้าถึงได้อย่างสมบูรณ์ผ่าน C และเป็นหนึ่งในสิ่งที่ทำให้มันเป็นภาษาแบบไดนามิกที่มีประสิทธิภาพ
Richard J. Ross III

1
"C runtime" เป็นเพียงไลบรารีไดนามิกที่มีรหัสสำหรับไลบรารีมาตรฐาน C เช่นเดียวกับ "C ++ runtime" มันค่อนข้างแตกต่างจากระบบรันไทม์เช่นเดียวกับ Objective-C นอกจากนี้ ... ในขณะที่ฉันสมมติว่าคุณสามารถใช้ Objective-C runtime ในทางเทคนิคได้นั่นเป็นเพียงโปรแกรม C ที่ใช้ Objective-C runtime - คุณไม่สามารถรวบรวมโปรแกรม Objective-C จริงใน C
celticminstrel

2
C ++ 11 มีหน่วยความจำแบบ A + อะตอมทำให้มันมากขึ้นเช่นประกอบแบบพกพา สิ่งเหล่านั้นไม่ใช่สิ่งระดับสูง แต่เป็นสิ่งระดับต่ำที่ C ++ ก่อนหน้านี้ขาดการสนับสนุนแบบพกพา แต่ปริมาณของ UB ใน C ++ ถ้าคุณทำอะไรผิดมันทำให้แตกต่างจากภาษาที่ใช้ VM เช่น Java และยังแตกต่างจากภาษาแอสเซมบลีที่เฉพาะเจาะจง เช่นการลงนามล้นเป็น UB ทั้งหมดในแหล่ง C ++ และคอมไพเลอร์สามารถปรับให้เหมาะสมตามความเป็นจริงแม้ว่าการรวบรวมเพื่อให้บอกว่า x86 แต่ใน asm บนแพลตฟอร์มเกือบทั้งหมดมันจะล้อมรอบ Modern C ++ อยู่ไกลจากภาษาแอสเซมบลีแบบพกพามาก
Peter Cordes

11

หากคุณต้องการเข้าใจการตัดสินใจการออกแบบโดยรอบ C ++ ให้ค้นหาสำเนาของคู่มืออ้างอิง C + Annotatedโดย Ellis และ Stroustrup ยังไม่ทันสมัยกับมาตรฐานล่าสุด แต่มันผ่านมาตรฐานดั้งเดิมและอธิบายว่าสิ่งต่าง ๆ ทำงานอย่างไรและบ่อยครั้งพวกเขาได้มาในแบบนั้น


6
นอกจากนี้การออกแบบและวิวัฒนาการของ C ++ โดย Stroustrup
James Hopkin

9

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

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

แต่คุณสามารถก้าวออกนอกภาษาและได้รับความสามารถในการสะท้อนเต็ม คำตอบของการอภิปรายสแต็คล้นอื่นในการสะท้อนใน Cอธิบายเรื่องนี้


7

Reflection สามารถเป็นและถูกนำไปใช้ใน c ++ มาก่อน

ไม่ใช่คุณลักษณะ c ++ ดั้งเดิมเนื่องจากมีค่าใช้จ่ายสูง (หน่วยความจำและความเร็ว) ที่ไม่ควรตั้งค่าตามค่าเริ่มต้นโดยภาษา - ภาษาคือ "เชิงประสิทธิภาพสูงสุดตามค่าเริ่มต้น"

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


3
และคุณไม่ได้จัดส่งสัญลักษณ์เพราะจะช่วยให้ลูกค้า / คู่แข่งของคุณดูรหัสของคุณ ... นี่มักจะถือว่าเป็นสิ่งที่ไม่ดี
gbjbaanb

คุณขวาฉันไม่ได้คิดเกี่ยวกับปัญหารหัสนิทรรศการ :)
Klaim

6

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


1
ฉันไม่เข้าใจว่าการเพิ่มประสิทธิภาพเชิงรุกของคอมไพเลอร์เป็นจุดแข็งอย่างไร คุณสามารถทำอย่างละเอียด? หาก linker สามารถลบคำจำกัดความอินไลน์ฟังก์ชันที่ซ้ำกันได้ปัญหาของข้อมูลการสะท้อนซ้ำคืออะไร ยังไม่ได้เพิ่มข้อมูลสัญลักษณ์ลงในไฟล์อ็อบเจ็กต์สำหรับนักดีบั๊กหรือไม่
Rob Kennedy

1
ปัญหาคือข้อมูลสะท้อนของคุณอาจไม่ถูกต้อง ถ้าคอมไพเลอร์กำจัด 80% ของคำจำกัดความของคลาสเมทาดาทาสะท้อนกลับของคุณจะบอกว่าอะไร? ใน C # และ Java ภาษารับประกันว่าถ้าคุณกำหนดคลาสจะยังคงมีการกำหนดไว้ C ++ ช่วยให้คอมไพเลอร์ปรับให้เหมาะสม
jalf

1
@Rob การปรับให้เหมาะสมเป็นอีกจุดหนึ่งไม่เชื่อมโยงกับความซับซ้อนหลายคลาส ดูความคิดเห็นของ @ jalf (และคำตอบของเขา) สำหรับสิ่งที่ฉันหมายถึง
Johannes Schaub - litb

4
หากฉันสร้างการสะท้อนให้เห็นถึง <T> ก็อย่าทิ้งข้อมูลใด ๆ ของ T ดูเหมือนว่าจะเป็นปัญหาที่แก้ไม่ตก
โจเซฟ Garvin

3

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

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


2

ตามที่อลิสแตร์เบิร์น, subtyping ไม่สามารถรับประกันได้ในสภาพแวดล้อมที่สะท้อนแสง

การสะท้อนกลับมีความเกี่ยวข้องกับระบบการพิมพ์แบบแฝง ใน C ++ คุณรู้ว่าคุณมีประเภทไหนและคุณรู้ว่าคุณสามารถทำอะไรได้บ้าง


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

2

การสะท้อนอาจเป็นทางเลือกเช่นคำสั่ง preprocessor สิ่งที่ต้องการ

#pragma enable reflection

ด้วยวิธีนี้เราจะได้สิ่งที่ดีที่สุดทั้งสองโลกโดยไม่ต้องสร้างห้องสมุด pragma นี้โดยไม่มีการไตร่ตรอง (ไม่มีค่าใช้จ่ายใด ๆ ตามที่กล่าวไว้) จากนั้นมันจะเป็นนักพัฒนาส่วนบุคคลไม่ว่าจะต้องการความเร็วหรือความสะดวกในการใช้งาน


2

ถ้า C ++ สามารถมี:

  • ข้อมูลสมาชิกคลาสสำหรับชื่อตัวแปรชนิดตัวแปรและโมดิconstฟายเออร์
  • ฟังก์ชันอาร์กิวเมนต์ iterator (เฉพาะตำแหน่งแทนชื่อ)
  • ข้อมูลสมาชิกคลาสสำหรับชื่อฟังก์ชันชนิดส่งคืนและconstตัวแก้ไข
  • รายการของคลาสแม่ (ในลำดับเดียวกันตามที่กำหนดไว้)
  • ข้อมูลสำหรับสมาชิกแม่แบบและคลาสผู้ปกครอง; เทมเพลตที่ขยาย (หมายถึงประเภทจริงจะพร้อมใช้งานสำหรับ reflect API และไม่ใช่ 'ข้อมูลเทมเพลตของวิธีไปที่นั่น')

นั่นก็เพียงพอแล้วที่จะสร้างห้องสมุดที่ใช้งานง่าย ๆ ที่ crux ของการประมวลผลข้อมูลที่แพร่หลายในแอปพลิเคชั่นเว็บและฐานข้อมูลทุกวันนี้

ตัวอย่างเช่นข้อมูลพื้นฐานที่สนับสนุนโดยQ_PROPERTYแมโคร (ส่วนหนึ่งของ Qt Framework) http://qt.nokia.com/doc/4.5/properties.htmlขยายเพื่อครอบคลุมวิธีการเรียนและ e) - จะเป็นประโยชน์อย่างยิ่งต่อ C ++ และ ชุมชนซอฟต์แวร์โดยทั่วไป

แน่นอนการสะท้อนที่ฉันอ้างถึงจะไม่ครอบคลุมความหมายทางความหมายหรือปัญหาที่ซับซ้อนมากขึ้น (เช่นความคิดเห็นหมายเลขบรรทัดซอร์สโค้ดการวิเคราะห์การไหลของข้อมูล ฯลฯ ) - แต่ฉันไม่คิดว่าสิ่งเหล่านั้นจะต้องเป็นส่วนหนึ่งของมาตรฐานภาษา


@Vlad: ใช่ถ้ามีฟีเจอร์ที่สนับสนุนการสะท้อนกลับไปยังภาษานั้นคุณจะได้รับการสะท้อนในภาษานั้น นี่น่าจะเกิดขึ้นได้หากคณะกรรมการภาษาประกาศและฉันคิดว่าพวกเขาไม่ได้เป็นของปี 2011 และฉันสงสัยว่าจะมีมาตรฐาน C ++ อีกหนึ่งมาตรฐานก่อนปี ค.ศ. 2020 ดังนั้นความคิดที่ดี ในระหว่างนี้หากคุณต้องการความก้าวหน้าคุณอาจต้องออกไปนอก C ++
Ira Baxter


0

การสะท้อนกลับใน C ++ ฉันเชื่อว่ามีความสำคัญอย่างยิ่งหากจะต้องใช้ C ++ เป็นภาษาสำหรับการเข้าถึงฐานข้อมูลการจัดการเซสชันของเว็บ / http และการพัฒนา GUI การขาดการสะท้อนจะป้องกัน ORMs (เช่น Hibernate หรือ LINQ), ตัวแยกวิเคราะห์ XML และ JSON ที่ติดตั้งคลาส, การทำให้เป็นอนุกรมของข้อมูลและอื่น ๆ อีกมากมาย

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

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

ทั้ง Boost serialization และกลไกอื่น ๆ ไม่สามารถแก้ปัญหาการสะท้อนได้จริง - มันต้องทำโดยคอมไพเลอร์ - และเมื่อเสร็จแล้ว C ++ จะถูกคิดอีกครั้งในโรงเรียนและใช้ในซอฟต์แวร์ที่จัดการกับการประมวลผลข้อมูล

สำหรับฉันปัญหานี้ # 1 (และการคิดเธรดเบื้องต้นแบบไร้เดียงสาเป็นปัญหา # 2)


4
ใครบอกว่าจะใช้C ++ เป็นภาษาสำหรับ DB Access, hnadling หรือ gui dev ของเซสชันบนเว็บ มีภาษาที่ดีกว่ามากมายสำหรับใช้ในสิ่งนั้น และสวิตช์เวลาคอมไพล์จะไม่แก้ปัญหา โดยปกติแล้วการตัดสินใจเปิดใช้งานหรือปิดใช้งานการสะท้อนจะไม่เป็นแบบต่อไฟล์ มันสามารถทำงานได้หากเปิดใช้งานในแต่ละประเภท หากโปรแกรมเมอร์สามารถระบุด้วยแอททริบิวต์หรือคล้ายกันเมื่อกำหนดประเภทว่าควรสร้างเมทาดาทาสะท้อนหรือไม่ก็ตาม แต่เป็นสวิตช์ระดับโลก คุณจะง่อย 90% ของ lnaguage เพื่อทำให้มันง่ายขึ้น 10%
jalf

จากนั้นถ้าฉันต้องการโปรแกรมที่ข้ามแพลตฟอร์มและเข้าถึง gui ฉันควรใช้อะไร การแกว่งของ Java ที่ไม่ยืดหยุ่น? หน้าต่างเท่านั้น C #? แต่ควรบอกความจริงและความจริงก็คือมีโปรแกรมมากมายที่ถูกคอมไพล์ในโค้ดที่ปฏิบัติการได้และมีอินเตอร์เฟส gui และการเข้าถึงฐานข้อมูลดังนั้นพวกเขาจึงต้องใช้ฐานข้อมูลและ gui บางส่วน ... t ใช้ QT (ควรมีชื่อว่า MT (ชุดเครื่องมือมอนสเตอร์))
Coyote21

1
@ Coyote21: C # ยังไม่ได้ใช้ Windows อย่างเดียวมานานหลายปี (แม้ว่าฉันไม่ใช่แฟนของ Mono แต่ก็ใช้งานได้ดีสำหรับทุกสิ่ง) และ Swing ไม่ใช่ชุดเครื่องมือ GUI สำหรับ Java เท่านั้น ความจริงจะบอกว่าอย่างใดอย่างหนึ่งจะเป็นทางเลือกที่ดีกว่าถ้าคุณต้องการข้ามแพลตฟอร์ม C ++ ค่อนข้างจะมีส่วนเฉพาะของแพลตฟอร์มอยู่ที่นี่เสมอหรือถ้าคุณทำอะไรที่ไม่สำคัญ
cHao

ไม่มีเหตุผลใดที่คุณต้องการภาพสะท้อนของ ORM คุณสามารถทำสิ่งเหล่านี้ได้ด้วยเทมเพลต มีพวงของพื้นที่กรอบที่ให้ ORM สำหรับ C ++
MrFox

0

มันเป็นพื้นเพราะมันเป็น "ตัวเลือกพิเศษ" หลายคนเลือก C ++ สำหรับภาษาเช่น Java และ C # เพื่อให้สามารถควบคุมเอาต์พุตคอมไพเลอร์เช่นโปรแกรมขนาดเล็กลงและ / หรือเร็วขึ้น

หากคุณเลือกที่จะเพิ่มการสะท้อนมีการแก้ปัญหาต่างๆที่มีอยู่

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