C โครงสร้างสามารถทำงานเหมือนมันมีฟังก์ชั่นหรือไม่?


13

ฉันใช้ C และstructs ที่ struct สามารถมีสมาชิก แต่ไม่ใช่ฟังก์ชั่น สมมติว่าสำหรับความเรียบง่ายที่ฉันต้องการที่จะสร้าง struct สำหรับสตริงที่ฉันชื่อstrและฉันต้องการที่จะสามารถที่จะทำstr.replace(int i, char c)ที่iเป็นดัชนีของสตริงและเป็นตัวละครที่จะแทนที่ตัวอักษรที่ตำแหน่งc iสิ่งนี้จะไม่เป็นไปได้หรือไม่เนื่องจาก structs ไม่มีฟังก์ชั่นหรือยังมีวิธีที่เราสามารถใช้พฤติกรรมนี้และเลียนแบบได้ว่าโครงสร้างอาจมีฟังก์ชั่น (ง่าย) ที่จริง ๆ แล้วคือ struct คัดลอกตัวเองไปที่ struct ใหม่ เขตข้อมูลซึ่งจะทำอย่างไร

ดังนั้นreplaceอาจเป็นสมาชิกที่สามของโครงสร้างที่ชี้ไปที่โครงสร้างใหม่ที่มีการปรับปรุงเมื่อมีการเข้าถึงหรือคล้ายกัน ทำได้หรือไม่ หรือมีบางอย่างในตัวหรือทฤษฎีหรือกระบวนทัศน์ที่ป้องกันความตั้งใจของฉัน

พื้นหลังคือฉันกำลังเขียนรหัส C และฉันพบว่าตัวเองมีฟังก์ชั่นการฟื้นฟูที่ฉันรู้ว่าเป็นตัวสร้างไลบรารีในภาษา OOP และ OOP จะเป็นวิธีที่ดีในการจัดการสตริงและคำสั่ง


5
ฉันคิดว่าคุณควรเขียนฟังก์ชั่นฟรีเพื่อทำสิ่งนี้ แต่ถ้าคุณมี Moxie จำเป็นอ่านcs.rit.edu/~ats/books/ooc.pdf
โรเบิร์ตฮาร์วีย์

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

29
แทนที่ (& str, i, c) จริง ๆ แล้วแย่กว่า str.replace (i, c) หรือไม่ คำถามของคุณไม่ได้เกี่ยวกับการแทนที่ฟังก์ชั่นมันเป็นเรื่องของความพยายามในการสร้างไวยากรณ์ใหม่เป็น C
whatsisname

1
@RobertHarvey ขอบคุณสำหรับ ลิงค์cs.rit.edu/~ats/books/ooc.pdf หนังสือดี (และราคาถูก)
John Forkosh

3
@whatsisname: ใน C คุณต้องผ่านตัวชี้โครงสร้างเพื่อการทำงานอยู่แล้วดังนั้นคุณท้ายด้วยstr.replace(&str, i, c)ล่ะค่ะ แน่นอนว่า C ++ จะส่งผ่านthisตัวชี้โดยอัตโนมัติ
Jonathan Leffler

คำตอบ:


21

ฟังก์ชั่นของคุณควรมีลักษณะเช่นนี้

void
replace(struct string * s, int i, char c);

สิ่งนี้ยอมรับตัวชี้ไปยังวัตถุเพื่อดำเนินการเป็นพารามิเตอร์แรก ใน C ++ สิ่งนี้เรียกว่าthis-pointer และไม่จำเป็นต้องประกาศอย่างชัดเจน (ตรงกันข้ามกับ Python ตรงนี้เพื่อ)

ในการเรียกฟังก์ชันของคุณคุณจะต้องผ่านตัวชี้นั้นอย่างชัดเจน โดยทั่วไปคุณแลกเปลี่ยนo.f(…)ไวยากรณ์สำหรับf(&o, …)ไวยากรณ์ ไม่ใช่เรื่องใหญ่.

เรื่องราวมีส่วนร่วมมากขึ้นถ้าคุณต้องการสนับสนุนความหลากหลาย ( virtualฟังก์ชั่นaka ) นอกจากนี้ยังสามารถจำลองใน C (ฉันได้แสดงไว้สำหรับคำตอบนี้) แต่มันไม่สวยที่จะทำด้วยมือ

ตามที่Jan Hudecได้แสดงความคิดเห็นคุณควรทำให้มันเป็นนิสัยที่จะนำหน้าชื่อฟังก์ชันด้วยชื่อประเภท (เช่นstring_replace) เนื่องจาก C ไม่มีช่องว่างชื่อดังนั้นจึงมีเพียงชื่อฟังก์ชันเดียวreplaceเท่านั้น


17
แน่นอนฟังก์ชั่นอาจจะต้องมีการเรียกstring_replaceเพราะ C ไม่ได้มีการทำงานมากเกินไปอย่างใดอย่างหนึ่งและคุณมีแนวโน้มที่จะมีคนอื่นreplaceสำหรับประเภทอื่น ๆ ...
Jan Hudec

2
ไม่สามารถตั้งชื่อstring_replaceได้ ชื่อขึ้นต้นด้วยstr, memหรือwcsตามด้วยตัวอักษรตัวพิมพ์เล็กจะถูกสงวนไว้สำหรับส่วนขยายในอนาคต
David Conrad

43

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

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


2
ตัวอย่างที่เด่นอื่น ๆ คือ CPython รหัสใช้แนวคิด OOP มากมาย แต่เป็นของแท้ 100% C
Bakuriu

@Bakuriu ฉันคิดว่าคุณสับสนCythonและCPython
cat

1
@cat เขาอาจหมายถึง Python C API, Cython ไม่บริสุทธิ์ 100% C. docs.python.org/c-api/intro.html
JAB

5
@cat ไม่ดูแหล่งที่มาของ CPython สิ่งต่าง ๆ ส่วนใหญ่จะทำโดยใช้กระบวนทัศน์ OOP และมี OOP API ที่ตรงกับ python API เป็นส่วนใหญ่
Bakuriu

1
@Bakuriu โอ้คุณหมายถึง runtime ของ Python, source และ C API ไม่ใช่ภาษา Python ความคิดเห็นของคุณไม่ได้ทำให้ชัดเจนมาก
แมว

8

ด้วยพอยน์เตอร์ของฟังก์ชั่นคุณสามารถทำได้:

str.replace(&str, i, c);

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

str.vtable->replace(&str, i, c);

3
ฉันมักจะยังคงเรียกมันว่าเป็น string_replace (& str, i, c) จากนั้นใช้ vtable ภายใน string_replace แทนที่จะให้ไซต์การโทรรู้เกี่ยวกับ vtable
Pete Kirkham

2
@Pete ชื่อขึ้นต้นด้วยstr(หรือmemหรือwcs) และตัวอักษรตัวพิมพ์เล็กจะถูกสงวนไว้โดย C string_replaceมาตรฐานสำหรับส่วนขยายในอนาคตจึงไม่เรียกมันว่า str_replaceไม่เป็นไร
David Conrad

3

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

ฉันเขียนโพสต์บล็อกในเรื่องนี้ตามคำถามจากนักเรียนคนหนึ่งของฉันเมื่อเร็ว ๆ นี้เกี่ยวกับโค้ดที่เหมือนหน้าจอใน C และ Go คุณสามารถอ่านได้ที่นี่:

บล็อกโพสต์บนอินเตอร์เฟสที่ไม่ใช่ OO

ดูว่ามันช่วยให้คุณมีความคิดใด ๆ

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

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