ฟีเจอร์ภาษาบางอย่างแม้ว่าจะเป็นสิ่งที่เพิ่มเข้ามาก็สามารถเปลี่ยนวิธีการใช้ภาษาได้อย่างแท้จริง จากตัวอย่างหนึ่งให้พิจารณากรณีนี้:
lock_mutex(&mutex);
// call some functions
...
unlock_mutex(&mutex);
หากรหัสข้างต้นเกี่ยวข้องกับฟังก์ชั่นการโทรที่ใช้งานใน C ++ เราอาจตกอยู่ในภวังค์แห่งปัญหาเพราะหนึ่งในการเรียกฟังก์ชั่นเหล่านั้นอาจเกิดขึ้นและเราจะไม่ปลดล็อก mutex ในเส้นทางที่พิเศษเหล่านั้น
Destructors ไม่ได้อยู่ในขอบเขตของความสะดวกสบายอีกต่อไปที่จะช่วยโปรแกรมเมอร์หลีกเลี่ยงการลืมที่จะปล่อย / ทรัพยากรฟรี ณ จุดนั้น RAII กลายเป็นข้อกำหนดที่ใช้งานได้จริงเพราะมันเป็นไปไม่ได้อย่างมนุษย์ปุถุชนที่จะคาดการณ์ทุกบรรทัดของรหัสที่สามารถโยนในตัวอย่างที่ไม่น่าสนใจ (ไม่พูดถึงว่าบรรทัดเหล่านั้นอาจไม่ได้โยนในขณะนี้ ลองอีกตัวอย่าง:
void f(const Foo* f1)
{
Foo f2;
memcpy(&f2, f1, sizeof f2);
...
}
รหัสดังกล่าวในขณะที่โดยทั่วไปไม่เป็นพิษเป็นภัยใน C ก็เหมือนขุมนรกที่เกิดความหายนะใน C ++ เพราะmemcpy
bulldozes เหนือบิตและไบต์ของวัตถุเหล่านี้และข้ามสิ่งต่าง ๆ เช่นตัวสร้างสำเนา ฟังก์ชั่นดังกล่าวเช่นmemset
, realloc
, memcpy
ฯลฯ ในขณะที่เครื่องมือในชีวิตประจำวันในหมู่นักพัฒนา C ใช้ในการมองสิ่งในทางที่ค่อนข้างเป็นเนื้อเดียวกันของบิตและไบต์ในหน่วยความจำไม่ได้สอดคล้องกับความซับซ้อนมากยิ่งขึ้นและระบบการพิมพ์ของภาษา C ++ C ++ สนับสนุนมุมมองที่เป็นนามธรรมของประเภทที่ผู้ใช้กำหนด
ดังนั้นสิ่งประเภทนี้ไม่อนุญาตให้ C ++ อีกต่อไปโดยใครก็ตามที่ต้องการใช้อย่างถูกต้องเพื่อดูว่าเป็น "superset" ของ C. ภาษาเหล่านี้ต้องใช้ความคิดระเบียบวินัยและวิธีคิดที่แตกต่างกันมาก .
ฉันไม่ได้อยู่ในค่ายที่เห็นว่า C ++ นั้นดีกว่าในทุก ๆ ทางและที่จริงแล้ว libs บุคคลที่สามที่ฉันโปรดปรานส่วนใหญ่คือไลบรารี C ด้วยเหตุผลบางอย่าง ฉันไม่รู้ว่าทำไม แต่ C libs มักจะมีความเรียบง่ายกว่าในธรรมชาติ (อาจเป็นเพราะการขาดระบบประเภทที่หลากหลายทำให้นักพัฒนามุ่งเน้นไปที่การให้ฟังก์ชั่นที่จำเป็นน้อยที่สุดโดยไม่ต้องสร้างชุดนามธรรมขนาดใหญ่ แม้ว่าฉันมักจะจบลงด้วยการเพียงแค่ใส่แผ่นซีดี C ++ ไว้รอบตัวพวกเขาเพื่อทำให้การใช้งานง่ายขึ้นและปรับแต่งการใช้งานของพวกเขาตามวัตถุประสงค์ของฉัน ฉันชอบความเรียบง่ายแบบมินิมัลลิสต์เป็นคุณลักษณะที่น่าสนใจของห้องสมุดสำหรับผู้ที่ใช้เวลาเพิ่มในการแสวงหาคุณสมบัติดังกล่าวและบางทีซีมีแนวโน้มที่จะสนับสนุนสิ่งนั้น
ฉันชอบ C ++ บ่อยกว่า แต่ฉันจริง ๆ ต้องใช้ C APIs ค่อนข้างบ่อยสำหรับความเข้ากันได้ของไบนารีที่กว้างที่สุด (และสำหรับ FFIs) แม้ว่าฉันมักจะใช้พวกเขาใน C ++ ทั้งๆที่ใช้ C สำหรับส่วนหัว แต่บางครั้งเมื่อคุณไปในระดับต่ำจริง ๆ เช่นระดับของตัวจัดสรรหน่วยความจำหรือโครงสร้างข้อมูลระดับต่ำมาก (และฉันแน่ใจว่ามีตัวอย่างเพิ่มเติมในหมู่ผู้ที่เขียนโปรแกรมฝังตัว) บางครั้งมันอาจเป็นประโยชน์ สามารถสันนิษฐานได้ว่าประเภทและข้อมูลที่คุณทำงานด้วยนั้นขาดคุณสมบัติบางอย่างเช่น vtables, costructors และ destructors เพื่อให้เราสามารถปฏิบัติต่อพวกเขาเป็นบิตและไบต์เพื่อสลับไปมาคัดลอกฟรีจัดสรรใหม่ สำหรับปัญหาระดับต่ำโดยเฉพาะอย่างยิ่งบางครั้งมันอาจเป็นประโยชน์ในการทำงานกับระบบประเภทที่ง่ายกว่าที่ C ให้
ชี้แจง
หนึ่งความคิดเห็นที่น่าสนใจที่นี่ฉันต้องการที่จะตอบสนองในเชิงลึกอีกเล็กน้อย (ฉันพบว่าความคิดเห็นที่นี่เข้มงวดมากกับจำนวนอักขระ):
memcpy(&f2, f1, sizeof f2);
ยังเป็น "ขุมพลังแห่งหายนะ" ใน C หาก Foo มีพอยน์เตอร์ที่เป็นเจ้าของหรือแย่กว่านั้นเนื่องจากคุณขาดเครื่องมือในการจัดการกับสิ่งนั้น
นั่นเป็นประเด็นที่ยุติธรรม แต่ทุกสิ่งที่ฉันสนใจอยู่นั้นมีความสำคัญกับระบบประเภทของ C ++ และด้วยความเคารพ RAII หนึ่งในเหตุผลที่เช่น X-rayish ไบต์การคัดลอกmemcpy
หรือqsort
ประเภทของการทำงานก่อให้เกิดน้อยของอันตรายในทางปฏิบัติใน C คือการทำลายf1
และf2
ข้างต้นเป็นอย่างชัดเจน (ถ้าพวกเขาจำเป็นต้องมีการทำลายที่ไม่น่ารำคาญ) ในขณะที่เมื่อ destructors ย้ายเข้าไปอยู่ในภาพ พวกเขากลายเป็นสิ่งที่บอกเป็นนัยและเป็นแบบอัตโนมัติ (บ่อยครั้งที่มีคุณค่าต่อนักพัฒนา) นั่นไม่ได้พูดถึงสถานะที่ซ่อนเร้นเช่น vptrs และอื่น ๆ ซึ่งฟังก์ชั่นดังกล่าวจะผลักไสไล่ส่ง หากf1
เป็นเจ้าของพอยน์เตอร์และf2
ตื้นคัดลอกพวกเขาในบริบทชั่วคราวบางอย่างแล้วมันไม่มีปัญหาถ้าเราไม่พยายามที่จะฟรีพอยน์เตอร์ที่เป็นเจ้าของเป็นครั้งที่สอง ด้วย C ++ นั่นคือสิ่งที่คอมไพเลอร์จะต้องการทำโดยอัตโนมัติ
และนั่นจะยิ่งใหญ่กว่าถ้าโดยทั่วไปใน C " ถ้า Foo เป็นเจ้าของพอยน์เตอร์" เนื่องจาก explicitness ที่จำเป็นในการจัดการทรัพยากรมักจะทำให้สิ่งที่ยากต่อการมองข้ามในขณะที่ใน C ++ เราสามารถทำให้ UDT ไม่เป็นเรื่องเล็กน้อย ที่สร้างขึ้น / ทำลายได้โดยเพียงทำให้มันเก็บตัวแปรสมาชิกใด ๆ ที่ไม่สามารถสร้างขึ้น / ทำลายได้เล็กน้อย (ในทางที่เป็นประโยชน์โดยทั่วไปมากอีกครั้ง แต่ไม่ใช่ถ้าเราถูกล่อลวงให้ใช้ฟังก์ชั่นเช่นmemcpy
หรือrealloc
)
ประเด็นหลักของฉันคือไม่พยายามโต้แย้งข้อดีใด ๆ ของ explicitness นี้ (ฉันจะบอกว่าถ้ามีพวกเขามักจะชั่งน้ำหนักลงโดยข้อเสียของความน่าจะเป็นที่เพิ่มขึ้นของข้อผิดพลาดของมนุษย์ที่มาพร้อมกับมัน) แต่เพียงเพื่อบอกว่า ฟังก์ชั่นเช่นmemcpy
และmemmove
และqsort
และmemset
และrealloc
และอื่น ๆ ไม่มีสถานที่ในภาษาที่มี UDT ซึ่งมีคุณสมบัติและความสามารถมากมายเช่น C ++ ในขณะที่พวกเขามีอยู่โดยไม่คำนึงถึงฉันคิดว่ามันคงไม่เป็นการโต้แย้งที่จะกล่าวว่านักพัฒนา C ++ ส่วนใหญ่จะฉลาดเพื่อหลีกเลี่ยงการใช้งานเช่นภัยพิบัติ d ยืนยันว่าพวกเขามีปัญหาน้อยกว่าใน C ด้วยเหตุผลง่ายๆว่าระบบการพิมพ์ของมันนั้นพื้นฐานมากขึ้นและอาจจะ "โง่" การเอ็กซเรย์ชนิด C และปฏิบัติต่อมันเป็นบิตและไบต์จะเกิดข้อผิดพลาดได้ง่าย การทำเช่นนั้นใน C ++ นั้นอาจจะผิดพลาดทันทีเพราะฟังก์ชั่นดังกล่าวกำลังต่อสู้กับคุณสมบัติพื้นฐานของภาษาและสิ่งที่มันกระตุ้นระบบการพิมพ์
ที่จริงแล้วสิ่งที่ดึงดูดความสนใจมากที่สุดสำหรับฉันของ C อย่างไรก็ตามโดยเฉพาะอย่างยิ่งกับวิธีการที่เกี่ยวข้องกับการทำงานร่วมกันของภาษา มันจะยากยิ่งกว่าที่จะทำบางสิ่งบางอย่างเช่น FFI ของ C # เพื่อทำความเข้าใจกับระบบแบบเต็มรูปแบบและคุณสมบัติภาษาของ C ++ ลงไปที่ตัวสร้าง, destructors, ข้อยกเว้น, ฟังก์ชันเสมือน, การโอเวอร์โหลดของฟังก์ชัน / วิธี การสืบทอด ฯลฯ ด้วย C มันเป็นภาษาที่ค่อนข้างมืดมนซึ่งค่อนข้างเป็นมาตรฐานเท่าที่ API ในรูปแบบที่ภาษาต่าง ๆ สามารถนำเข้าโดยตรงผ่าน FFIs หรือโดยอ้อมผ่านฟังก์ชันการส่งออก C API บางรูปแบบในรูปแบบที่ต้องการ (เช่น Java Native Interface ) และนั่นคือสิ่งที่ฉันส่วนใหญ่ไม่มีทางเลือกนอกจากต้องใช้ C เนื่องจากความสามารถในการทำงานร่วมกันของภาษานั้นเป็นข้อกำหนดที่ใช้งานได้จริงในกรณีของเรา
แต่คุณรู้ไหมว่าฉันเป็นนักปฏิบัตินิยม (หรืออย่างน้อยก็พยายามเป็น) ถ้า C เป็นภาษาที่หยาบคายและโหดร้ายผิดพลาดได้ง่ายน่ารังเกียจเพื่อนร่วมงาน C ++ บางคนของฉันอ้างว่ามันเป็น (และฉันจะนับตัวเองเป็นผู้ที่ชื่นชอบ C ++ ยกเว้นว่าอย่างใดก็ตามมันไม่ได้นำความเกลียดชัง C มาด้วย) ในทางตรงกันข้ามมันมีผลตรงกันข้ามกับฉันที่ทำให้ฉันซาบซึ้งทั้งสองภาษาดีกว่าในแง่ของตัวเองและความแตกต่าง) แล้วฉันก็คาดหวังว่าจะปรากฏในโลกแห่งความจริงในรูปแบบของ buggiest และ leakiest และ มีการเขียนผลิตภัณฑ์และห้องสมุดที่ไม่น่าเชื่อถือใน C. และฉันไม่พบสิ่งนั้น ฉันชอบ Linux, ฉันชอบ Apache, Lua, zlib ฉันพบว่า OpenGL สามารถทนต่อความต้องการฮาร์ดแวร์แบบขยับได้เช่น Gimp, libpng, Cairo เป็นต้น อย่างน้อยสิ่งใดก็ตามที่ภาษาโพสท่าดูเหมือนจะไม่เป็นอุปสรรคต่อการเขียนห้องสมุดและผลิตภัณฑ์เจ๋ง ๆ ในมือที่มีความสามารถและนั่นคือทั้งหมดที่ฉันสนใจดังนั้นฉันจึงไม่เคยเป็นคนที่สนใจหลงใหลมากที่สุด สงครามภาษายกเว้นที่จะดึงดูดความสนใจในทางปฏิบัติและพูดว่า "เฮ้มีสิ่งที่น่าสนใจอยู่ที่นั่นเรามาเรียนรู้วิธีที่พวกเขาสร้างมันขึ้นมาและอาจจะมีบทเรียนที่น่าสนใจไม่เฉพาะเจาะจงกับธรรมชาติของภาษา ภาษาใดก็ตามที่เราใช้ " :-D