เหตุใด C จึงไม่ถือว่าเป็นภาษา 'เชิงวัตถุ'


92

ดูเหมือนว่า C มีวัตถุเสมือนของตัวเองเช่น 'structs' ซึ่งถือได้ว่าเป็นวัตถุ (ในระดับสูงที่เราคิดว่าปกติ)

และไฟล์ C เองก็แยก "โมดุล" เป็นหลักใช่มั้ย ถ้าเช่นนั้นโมดูลก็ไม่เหมือน 'วัตถุ' ด้วยใช่ไหม ฉันสับสนว่าทำไม C ซึ่งดูเหมือนคล้ายกับ C ++ ถือเป็นภาษา "ขั้นตอน" ในระดับต่ำซึ่ง C ++ เป็นระดับสูง "เชิงวัตถุ"

* แก้ไข: (ชี้แจง) สาเหตุและสถานที่มีการลากเส้นสำหรับ 'วัตถุ' คืออะไรและไม่?


40
ทั้งหมด - ทำไมลงคะแนนเสียง? มันเป็นคำถามพื้นฐาน แต่ไม่ใช่คำถามที่ไม่ดี
Jon Hopkins

7
คุณสามารถใช้หลักการ OO ได้อย่างมีประสิทธิภาพใน C (และผู้ที่เขียนโค้ด C ที่ดีมักจะทำ) แต่ภาษาไม่ได้ถูกสร้างขึ้นทำให้ง่ายขึ้นเนื่องจากมีภาษาใหม่ ๆ มากมาย
asveikau

5
C นั้นมีวิธีการที่แตกต่างกันง่ายกว่าและชัดเจนกว่า(อย่างน้อยในหมู่ชุมชนโอเพนซอร์ซ) ที่มีวิธีการที่เป็นนามธรรม C ++ มีแนวโน้มที่จะเป็นโรงไฟฟ้าที่เป็นนามธรรมและอนุญาตให้มีสิ่งที่ดีมากมาย แต่มาพร้อมกับค่าใช้จ่ายในการทำความเข้าใจวิธีการ [ไม่] ใช้งานได้อย่างถูกต้องซึ่งบ่อยกว่าไม่หายไปในโปรแกรมทั่วไป ดูคำตอบแบบเต็มของฉันสำหรับรายละเอียดเพิ่มเติม
Yam Marcovic

1
ไม่นาน: โครงสร้างไม่สามารถมีวิธีได้ (ตัวชี้ไปยังฟังก์ชั่นไม่ได้ตัดค่อนข้าง)
เอสเอฟ

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

คำตอบ:


101

ดูเหมือนว่า C มีวัตถุเสมือนของตัวเองเช่น 'structs' ที่ถือได้ว่าเป็นวัตถุ

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

(OOP) เป็นกระบวนทัศน์การเขียนโปรแกรมโดยใช้ "วัตถุ" - โครงสร้างข้อมูลประกอบด้วยเขตข้อมูลและวิธีการพร้อมกับการโต้ตอบ

C structs ประกอบด้วยเขตข้อมูลและวิธีการพร้อมกับการโต้ตอบหรือไม่? เลขที่

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

C structs ทำสิ่งเหล่านี้ในแบบ "ชั้นหนึ่ง" หรือไม่? ไม่ภาษาใช้กับคุณได้ทุกย่างก้าว

วิธีการเชิงวัตถุสนับสนุนให้โปรแกรมเมอร์วางข้อมูลที่ไม่สามารถเข้าถึงได้โดยตรงจากส่วนที่เหลือของโปรแกรม

C structs ทำสิ่งนี้หรือไม่? เลขที่

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

C structs ทำสิ่งนี้หรือไม่? ใช่.

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

เลขที่

แต่ละวัตถุมีความสามารถในการรับข้อความประมวลผลข้อมูลและส่งข้อความไปยังวัตถุอื่น

struct สามารถส่งและรับข้อความได้หรือไม่? ไม่มันสามารถประมวลผลข้อมูลได้หรือไม่ เลขที่

โครงสร้างข้อมูล OOP มีแนวโน้มที่จะ "พกพาผู้ปฏิบัติงานไปด้วย"

สิ่งนี้เกิดขึ้นใน C หรือไม่? เลขที่

การจัดส่งแบบไดนามิก ... การห่อหุ้ม ... ความหลากหลายชนิดย่อย ... การสืบทอดวัตถุ ... การเรียกซ้ำเปิด ... คลาสของวัตถุ ... อินสแตนซ์ของคลาส ... วิธีการที่ทำหน้าที่กับวัตถุที่แนบ ... ข้อความที่ผ่านมา .. . สิ่งที่เป็นนามธรรม

มีคุณสมบัติเหล่านี้ของ C structs หรือไม่ เลขที่

คุณคิดว่าคุณลักษณะของ structs ใดเป็น "เชิงวัตถุ" อย่างแม่นยำ? เพราะผมไม่สามารถหาใด ๆอื่น ๆ นอกเหนือจากความจริงที่ว่า structs กำหนดประเภท

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

และไฟล์ C เองก็แยก "โมดุล" เป็นหลักใช่มั้ย ถ้าเช่นนั้นโมดูลก็ไม่เหมือน 'วัตถุ' ด้วยใช่ไหม

คุณคิดว่าโมดูลลักษณะใดที่ทำให้พวกมันทำหน้าที่เหมือนวัตถุ โมดูลสนับสนุน abstraction, encapsulation, messaging, modularity, polymorphism และการสืบทอดหรือไม่?

สิ่งที่เป็นนามธรรมและการห่อหุ้มค่อนข้างอ่อนแอ เห็นได้ชัดว่าโมดูลเป็นแบบแยกส่วน; นั่นเป็นเหตุผลที่พวกเขาเรียกว่าโมดูล ส่งข้อความ? เฉพาะในแง่ที่ว่าการเรียกใช้เมธอดเป็นข้อความและโมดูลสามารถมีเมธอดได้ ความแตกต่าง? Nope มรดก? Nope โมดูลเป็นตัวเลือกที่ค่อนข้างอ่อนสำหรับ "วัตถุ"


15
ฉันไม่เห็นด้วยว่า "การเลียนแบบ C ++" (คำศัพท์ของคุณ) ไม่ใช่สำนวน C. ตัวอย่างตัวนับหนึ่งจะเป็นวิธีที่เคอร์เนลระบบปฏิบัติการใช้การดำเนินการของไฟล์ - ใช้ Linux เป็นตัวอย่างซึ่งคุณมีโครงสร้างที่เต็มไปด้วยพอยน์เตอร์ของฟังก์ชัน พวกเขาอาจจะค่อนข้าง "เฉพาะโดเมน" (จำกัด เฉพาะการเขียนไดรเวอร์บน * ระวังพูด) แต่พวกเขาเป็นที่รู้จักและทำงานอย่างสะอาดพอสำหรับบางวัตถุประสงค์ นอกจากนี้ยังมีตัวอย่างของไลบรารี่โหมดผู้ใช้ที่มีแนวคิดเกี่ยวกับ OO อยู่พอสมควร ใช้ Gtk + และไลบรารีที่ขึ้นอยู่กับ เรียกว่าแฮ็คและคุณอาจจะถูก แต่สิ่งเหล่านี้ไม่น่ากลัวที่จะทำงานกับ
asveikau

5
@asveikau: ความคิดที่ว่าการฝึกเป็นเรื่องผิดปกติ (แม้ว่าจะไม่เคยได้ยิน) และ "แฮ็ค" ก็หมายความว่ามันเป็นตามคำจำกัดความไม่ใช่คำศัพท์?
อดัมโรบินสัน

19
@ asveikau: แน่นอนว่ามีหลายสิ่งที่คุณสามารถทำได้เพื่อทำให้โปรแกรม C เป็นแบบ OO มากขึ้น แต่อย่างที่คุณพูดมันต้องมีวินัยในการทำเช่นนั้น คุณสมบัติทางภาษานั้นไม่ได้นำพาคุณไปสู่การห่อหุ้มความหลากหลายรูปแบบการสืบทอดชั้นเรียนและอื่น ๆ แต่ผู้พัฒนาสามารถกำหนดรูปแบบดังกล่าวกับภาษา ไม่ได้หมายความว่า structs นั้นมีเหตุผลเหมือนกับวัตถุ Heck คุณสามารถเขียนโปรแกรมในลักษณะ OO ใน Lisp ด้วย แต่นั่นไม่ได้หมายความว่าเซลล์ข้อเสียเป็นวัตถุ
Eric Lippert

3
@asveikau ฉันขอแนะนำให้คุณการตีความ "สำนวนผิด" ของคุณในฐานะ "ของตัวเอง" นั้นอ่อนโยน ... :)
Benjol

8
@BillK: Structs ไม่สามารถมีรหัสใน C. Structs สามารถมีคำแนะนำการทำงานซึ่งเป็นข้อมูล คำแนะนำการทำงานไม่ได้รหัส รหัสเป็นสิ่งประดิษฐ์ที่เป็นข้อความที่สร้างขึ้นโดยโปรแกรมเมอร์
Eric Lippert

46

คำสำคัญคือ "เชิง" ไม่ใช่ "วัตถุ" แม้ c ++ รหัสที่ใช้วัตถุ แต่ใช้พวกเขาเช่น structs ไม่ได้วัตถุที่มุ่งเน้น

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

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


2
+1 สำหรับการชี้ C ของเราสามารถเป็น OO มันไม่สะดวก แต่ก็สามารถทำได้
dietbuddha

มันง่ายกว่าที่จะสร้างวัตถุใน VBA แต่ฉันไม่คิดว่ามันจะ 'วางตัว' อย่างใดอย่างหนึ่ง
JeffO

VBA ฉันเรียกว่า "ตามวัตถุ" มันใช้วัตถุ แต่ไม่ใช่ polymorphically และในงานเล็ก ๆ น้อย ๆ ที่ฉันทำไปฉันไม่แน่ใจว่าคุณสามารถทำ polymorphism ได้ไม่ว่าคุณจะลองใช้การแสดงกายกรรมชนิดใด มันเป็นภาษาขั้นตอนที่มีการห่อหุ้ม
kylben

2
ภาษาส่วนใหญ่สามารถทำหน้าที่เป็น OO ภาษาที่ใช้งานได้ ความแตกต่างคือ "เชิง" และฉันไม่เคยได้ยินมาก่อน ฉันหวังว่าฉันจะลงคะแนนได้ถึง 3 ครั้งและยอมรับมันเป็นคำตอบที่ถูกต้อง
Bill K

1
@ kylben คงไม่ยืดเกินกว่าที่จะเก็บรหัส SQL ไว้ในตารางจากนั้นแตกไฟล์และเรียกใช้งาน (ทำให้ตารางเป็นวัตถุของคุณ) มันเป็นการทดลองที่น่าสนใจ อันที่จริงมันเป็นเรื่องเล็กน้อยที่ดึงดูด ...
Bill K

19

ขึ้นอยู่กับผู้บริหารระดับสูงสุด:

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

โครงสร้างมีข้อมูล แต่ไม่มีพฤติกรรมดังนั้นจึงไม่สามารถถือเป็นวัตถุได้

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

และนั่นคือก่อนที่คุณจะเข้าสู่การสืบทอดและความแตกต่าง ...


พฤติกรรมและข้อมูลในโมดูลมาไม่ได้อย่างไร สมาชิกไม่ได้ทำหน้าที่เป็น 'พฤติกรรม' ในข้อมูลที่มีอยู่ในโมดูลใช่หรือไม่
Dark Templar

4
ปัญหาคือพวกเขาไม่ได้ห่อหุ้มไม่ใช่ว่าพวกเขาไม่เกี่ยวข้อง
Eoin Carroll

วัตถุจริงๆแล้วมีศูนย์กลางอยู่ที่พฤติกรรมเป็นหลักไม่ใช่ข้อมูล ข้อมูลคือ / ควรเป็นพลเมืองชั้นสองใน OOP Structs แทนที่จะเป็นศูนย์กลางรอบ ๆ ข้อมูลและไม่มีพฤติกรรม
Sklivvz

1
@Dark Templar - Eoin พูดอะไร ... มันเป็นลักษณะของความสัมพันธ์ ฉันสามารถดูว่าคุณมาจากไหน - คุณสามารถใช้ Structs ภายในโมดูลในลักษณะที่เลียนแบบองค์ประกอบพื้นฐานบางอย่างของ OO แต่สิ่งที่คุณทำส่วนใหญ่จะขึ้นอยู่กับโปรแกรมเมอร์ที่ติดตั้งชุด ของกฎที่บังคับใช้ด้วยตนเองแทนที่จะให้ภาษาบังคับใช้ และทำไมคุณถึงต้องรำคาญ คุณไม่ได้รับผลประโยชน์ใด ๆ จาก OO - ไม่มีการสืบทอดเช่น - และคุณ จำกัด ตัวเอง
Jon Hopkins

นี่เป็นคำตอบที่ดีกว่าคำตอบที่ถูกต้อง
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

6

"structs" เป็นข้อมูลเท่านั้น การทดสอบอย่างรวดเร็วและสกปรกตามปกติของ "การวางแนววัตถุ" คือ: "มีโครงสร้างที่อนุญาตให้โค้ดและข้อมูลถูกห่อหุ้มเป็นหน่วยเดียวหรือไม่" C นั้นล้มเหลวและเป็นขั้นตอนดังนั้น C ++ ผ่านการทดสอบนั้น


6
มีวิธีแก้ไขปัญหา structs สามารถมีตัวชี้ฟังก์ชันคงที่ฟังก์ชันสมาชิก พวกเขาจะต้องมีthisตัวชี้ที่ชัดเจนแต่ในกรณีนั้นข้อมูลและวิธีการในการประมวลผลข้อมูลจะถูกห่อหุ้มภายในโครงสร้าง
Coder

@Brian Knoblauch: แต่ไฟล์ C ไม่ได้เป็นตัวห่อหุ้มข้อมูลและรหัส ??
Dark Templar

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

หน่วยการแปล >. <
Dark Templar

@Dark นักรบ: หน่วยการแปลเป็นแฟ้มแหล่งที่มาบวกอะไร#includeวันที่เป็นมันและลบอะไรลบออกโดยไม่ได้รับการรวมเงื่อนไข ( #if, #ifdefและชอบ)
David Thornley

5

C เช่นเดียวกับ C ++ มีความสามารถในการให้Data Abstractionซึ่งเป็นสำนวนหนึ่งของกระบวนทัศน์การเขียนโปรแกรมเชิงวัตถุที่มีอยู่ก่อนหน้านี้

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

OOP ใน C ++ เป็นการเพิ่มความหมายให้กับข้อมูลนามธรรม บางคนบอกว่ามันเป็นอันตรายในขณะที่คนอื่นคิดว่ามันเป็นเครื่องมือที่ดีเมื่อใช้อย่างถูกต้อง

  • C ++ ทำให้ตัวชี้นี้บอกเป็นนัยโดยไม่ต้องการให้ผู้ใช้ส่งต่อไปยัง "เมธอดของคลาส / โครงสร้าง" ตราบใดที่สามารถระบุได้ (อย่างน้อยก็บางส่วน)
  • C ++ ช่วยให้คุณสามารถ จำกัด การเข้าถึงวิธีการบางอย่าง (ฟังก์ชั่นชั้นเรียน) และช่วยให้ "การเขียนโปรแกรมเชิงป้องกัน" หรือ "การพิสูจน์อักษรแบบบ้าคลั่ง" เพิ่มเติม
  • C ++ ส่งเสริม abstractions โดยให้ความปลอดภัยประเภทที่สูงขึ้นโดยการแนะนำ
    1. ใหม่ผู้ประกอบการแทนmalloc + หล่อ
    2. เทมเพลตแทนโมฆะพอยน์เตอร์
    3. ฟังก์ชั่นแบบอินไลน์ที่ได้รับค่าพิมพ์แทนมาโคร
    4. สร้างขึ้นในหลายรูปแบบที่คุณไม่ต้องใช้ตัวเองที่ช่วยให้คุณสร้างลำดับชั้นนามธรรม , สัญญาและความเชี่ยวชาญ

อย่างไรก็ตามคุณจะพบว่า "แฮ็กเกอร์" หลายคนเทศนาว่า C นั้นมีความสามารถอย่างสมบูรณ์แบบในปริมาณที่เหมาะสมของนามธรรมและวิธีที่ค่าใช้จ่ายที่สร้างโดย C ++ นั้นเบี่ยงเบนความสนใจจากการแก้ปัญหาจริง

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

คนอื่นมักจะมองมันอย่างสมดุลมากขึ้นยอมรับทั้งข้อดีและข้อเสีย

C ทำให้ง่ายต่อการยิงตัวเองที่เท้า; C ++ ทำให้มันยากขึ้น แต่เมื่อคุณทำมันจะทำให้ทั้งขาของคุณหลุด - Bjarne Stroustrup


2

คุณต้องดูอีกด้านของเหรียญ: C ++

ใน OOP เราคิดว่าวัตถุนามธรรม (และออกแบบโปรแกรมให้สอดคล้องกัน) เช่นรถที่สามารถหยุดเร่งเลี้ยวซ้ายหรือขวา ฯลฯ โครงสร้างที่มีชุดของฟังก์ชั่นไม่ตรงกับแนวคิด

ด้วยวัตถุ "ของจริง" เราจำเป็นต้องซ่อนสมาชิกเช่นหรือเราสามารถมีมรดกที่แท้จริง "คือ" ความสัมพันธ์ "และอีกมากมาย

หลังจากอ่านความคิดเห็นด้านล่าง: มันถูกต้องที่ (เกือบ) ทุกอย่างสามารถทำได้ด้วย C (ที่เป็นจริงเสมอ) แต่ในแวบแรกฉันคิดว่าสิ่งที่แยก c จาก c ++ เป็นวิธีที่คุณคิดว่าเมื่อออกแบบโปรแกรม

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


ไม่แน่ใจจริงๆว่าทำไมโครงสร้างที่มี "กลุ่มของฟังก์ชั่น" ไม่ตรงกับแนวคิดหรือไม่ +1 สำหรับคำตอบ
Dark Templar

1
นอกเหนือจากการควบคุมการเข้าถึง (ส่วนตัว / ป้องกัน / สาธารณะ) ทุกอย่างอื่นสามารถทำได้ด้วย structs
Coder

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

1

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


1
ฉันเดาว่าคำถามคือ: ทำไมและที่วาดเส้นสำหรับวัตถุคืออะไรและสิ่งที่ไม่?
Dark Templar

1

Object Oriented หมายถึงทั้งรูปแบบสถาปัตยกรรม (หรือแม้กระทั่งรูปแบบเมตาดาต้า) และภาษาที่มีคุณสมบัติที่จะช่วยในการนำไปใช้หรือมอบอำนาจโดยใช้รูปแบบนี้

คุณสามารถใช้การออกแบบ "OO" (เดสก์ท็อป Gnome อาจเป็นตัวอย่างที่ดีที่สุดของ OO ใน C บริสุทธิ์) ฉันเคยเห็นสิ่งนี้ทำด้วย COBOL!

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

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


0

ลองดูที่นิยามของ OO:

  • การส่งข้อความ
  • encapsulation
  • การผูกปลาย

C ไม่มีสามตัวต่อไปนี้ โดยเฉพาะอย่างยิ่งมันไม่ได้ให้ข้อความซึ่งเป็นสิ่งที่สำคัญที่สุด


1
ฉันคิดว่าฉันต้องไม่เห็นด้วย แน่นอนที่สุดคุณสามารถส่งข้อความใน C - ทำงานกับ Objective C APIs จาก C และคุณพบว่าในเชิงลึก - และการผูกปลายสามารถทำได้ผ่านตัวชี้ฟังก์ชั่น แต่คุณไม่ได้รับน้ำตาล syntactic จำนวนมากเพื่อซ่อนมัน (การห่อหุ้มนั้นเป็นเรื่องง่ายใน C; ตัวชี้ไปยังประเภทโครงสร้างที่ไม่สมบูรณ์ทำงานได้อย่างสมบูรณ์)
Donal Fellows

การสืบทอดยังถือว่ามีความสำคัญใน OO และ C ไม่ได้ทำเช่นนั้น สิ่งที่ใกล้เคียงที่สุดในการห่อหุ้มใน C คือไฟล์แยกต่างหากที่สามารถมีstaticฟังก์ชั่นภายใน ( ) และสมาชิกข้อมูล
David Thornley

@DonalFellows ข้อความจริงที่ส่งผ่านใน Objective-C สามารถนำไปใช้อย่างง่ายดายในฐานะมาโคร C99 สิ่งเดียวที่คอมไพเลอร์ได้ทำคือสร้างโครงสร้างที่จำเป็นทั้งหมดแบบคงที่จากโค้ดระดับสูงสองสามบรรทัด คุณลักษณะส่วนใหญ่หากไม่ได้มีให้บริการทั้งหมดจาก C API
qpr

0

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

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

struct FooImpl;
typedef struct FooImpl *Foo;

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

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

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

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


0

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

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

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

และเราต้องใช้ซินแท็กซ์เหมือนfopen(file, ...); fclose(file);ซึ่งตรงข้ามกับfile.open(...); file.close();แต่โห่ใหญ่ ใครสนใจจริง ๆ อาจเป็นแค่คนที่โน้มน้าวให้ทำสิ่งนี้กับ IDE โดยอัตโนมัติ ฉันยอมรับว่าเป็นคุณลักษณะที่มีประโยชน์มากจากมุมมองเชิงปฏิบัติ แต่อาจไม่ใช่สิ่งที่จำเป็นต้องมีการอภิปรายว่าภาษานั้นเหมาะสำหรับ OOP หรือไม่

เราขาดความสามารถในการใช้protectedฟิลด์อย่างมีประสิทธิภาพ ฉันจะส่งทั้งหมดที่นั่น แต่ฉันไม่คิดว่ามีกฎเกณฑ์ที่ชัดเจนว่า " ทุกภาษา OO ควรมีคุณสมบัติที่อนุญาตให้ subclasses เข้าถึงสมาชิกของคลาสพื้นฐานที่ยังคงไม่สามารถเข้าถึงได้โดยไคลเอนต์ปกติ " นอกจากนี้ฉันไม่ค่อยเห็นกรณีการใช้งานสำหรับสมาชิกที่ได้รับความคุ้มครองซึ่งอย่างน้อยก็ไม่น่าสงสัยว่าจะกลายเป็นอุปสรรคในการบำรุงรักษา

และแน่นอนว่าเราต้อง "เลียนแบบ" polymorphism OO กับตารางของตัวชี้ฟังก์ชั่นและตัวชี้ไปยังพวกเขาสำหรับการจัดส่งแบบไดนามิกที่มีต้นแบบเล็ก ๆ น้อย ๆ ในการเริ่มต้นผู้กระเชอvtablesและvptrsแต่เล็กน้อยของสำเร็จรูปไม่เคยทำให้ฉันเศร้าโศกมาก

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

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


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

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

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

ใช่ฉันรู้ว่าผู้คนใช้ OOP ใน C อย่างไรขอบคุณ จุดของฉันคือว่าคำสั่งของคุณที่สร้างเป็น "ไม่ถือว่าโดยตรงข้อกำหนดเบื้องต้นสำหรับ OOP" มีข้อผิดพลาด
Nicol Bolas

ฉันเห็นว่า lemme ถูกต้องว่า ... แต่ในกรณีนั้นเราอาจจะบอกว่า C ให้การสนับสนุน (เพียงพอหรือไม่) แก่ผู้ทำลายล้างและผู้สร้าง?

-1

ไม่ใช่คำถามที่ไม่ดี

ถ้าคุณกำลังจะเรียก c ภาษา OO คุณจะต้องเรียกใช้ OO ภาษาขั้นตอนทั้งหมดด้วย ดังนั้นมันจะทำให้คำไม่มีความหมาย c ไม่มีภาษารองรับ OO ถ้ามี structs แต่ structs typesไม่มีคลาส

จริงๆแล้ว c ไม่มีคุณสมบัติมากมายเลยเมื่อเทียบกับภาษาส่วนใหญ่ ส่วนใหญ่ใช้สำหรับความเร็วความเรียบง่ายความนิยมและการสนับสนุนรวมถึงห้องสมุดมากมาย

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