Bisakah C struct berperilaku seperti itu memiliki fungsi?

13

Saya menggunakan C dan structs di mana sebuah struct dapat memiliki anggota tetapi tidak berfungsi. Asumsikan untuk kesederhanaan bahwa saya ingin membuat struct untuk string yang saya beri nama strdan saya ingin dapat melakukan di str.replace(int i, char c)mana iindeks string dan ckarakter untuk menggantikan karakter di posisi i. Apakah ini tidak pernah mungkin karena struct tidak dapat memiliki fungsi atau masih ada beberapa cara kita dapat menerapkan perilaku ini dan meniru bahwa struct dapat memiliki fungsi (sederhana) yang sebenarnya hanya struct menyalin sendiri ke struct baru dan memperbarui nya bidang, yang bisa dilakukan?

Jadi replacebisa menjadi anggota ketiga dari struct yang menunjuk ke sebuah struct baru yang diperbarui ketika diakses atau serupa. Bisakah itu dilakukan? Atau adakah sesuatu yang dibangun di dalam teori atau paradigma yang menghalangi niat saya?

Latar belakangnya adalah saya sedang menulis kode C dan saya menemukan kembali fungsi-fungsi yang saya tahu adalah library builtin dalam bahasa OOP dan bahwa OOP akan menjadi cara yang baik untuk memanipulasi string dan perintah.

Niklas
sumber
5
Jujur saya pikir Anda akan lebih baik menulis fungsi gratis untuk melakukan hal semacam ini. Namun, jika Anda memiliki moxie yang
Robert Harvey
5
Structs dapat menyertakan variabel yang merupakan pointer ke fungsi. Tidak ada warisan bawaan tetapi Anda dapat instantiate struct Anda dengan pointer menunjuk ke fungsi yang berbeda dengan tanda tangan yang sama. Anda akan sering ingin membuat parameter pertama ke fungsi pointer ke struct.
James McLeod
29
apakah ganti (& str, i, c) benar - benar jauh lebih buruk daripada str.replace (i, c)? Pertanyaan Anda sebenarnya bukan tentang mengganti fungsi, ini tentang mencoba menyinari sintaks baru ke C.
whatsisname
1
@RobertHarvey Terima kasih atas tautan cs.rit.edu/~ats/books/ooc.pdf . Buku yang bagus (dan harganya tepat).
John Forkosh
3
@whatsisname: Di C, Anda harus meneruskan pointer struktur ke fungsi, jadi Anda tetap berakhir dengan str.replace(&str, i, c)itu. C ++ mengotomatiskan lewat dari thispointer, tentu saja.
Jonathan Leffler

Jawaban:

21

Fungsi Anda akan terlihat seperti ini.

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

Ini menerima pointer ke objek untuk beroperasi sebagai parameter pertama. Dalam C ++, ini dikenal sebagai this-pointer dan tidak perlu dideklarasikan secara eksplisit. (Bandingkan ini dengan Python di mana harus.)

Untuk memanggil fungsi Anda, Anda juga akan melewatkan pointer itu secara eksplisit. Pada dasarnya, Anda menukar o.f(…)sintaksis dengan f(&o, …)sintaksis. Bukan masalah besar.

Cerita menjadi lebih terlibat jika Anda ingin mendukung polimorfisme ( virtualfungsi alias ). Itu juga dapat ditiru dalam C (saya sudah menunjukkannya untuk jawaban ini .) Tetapi tidak cukup untuk dilakukan dengan tangan.

Seperti yang dikomentari Jan Hudec , Anda juga sebaiknya membiasakan awalan nama fungsi dengan nama tipe (yaitu string_replace) karena C tidak memiliki spasi-nama sehingga hanya ada satu fungsi yang dinamai replace.

5gon12eder
sumber
17
Tentu saja fungsi tersebut mungkin harus dipanggil string_replace, karena C juga tidak memiliki fungsi yang berlebihan dan Anda mungkin memiliki beberapa lainnya replaceuntuk beberapa jenis lainnya ...
Jan Hudec
2
Tidak bisa disebutkan namanya string_replace. Nama yang dimulai dengan str,, mematau wcsdiikuti dengan huruf kecil dicadangkan untuk ekstensi di masa mendatang.
David Conrad
43

Structs dapat menampung fungsi pointer , tetapi itu benar-benar hanya diperlukan untuk metode virtual. Metode non-virtual dalam berorientasi objek C biasanya dilakukan dengan melewatkan struct sebagai argumen pertama ke fungsi biasa. Lihatlah Gobject untuk contoh yang baik dari kerangka kerja OOP untuk C. Ini menggunakan makro untuk menangani banyak pelat ketel yang diperlukan untuk pewarisan dan polimorfisme.

C diciptakan 44 tahun yang lalu. Ini adalah bahasa yang sangat populer untuk open source. Anda bukan orang pertama yang berpikir string C standar tidak pas untuk digunakan. Lakukan beberapa pencarian untuk perpustakaan string C. Anda tidak perlu menemukan kembali roda.

Karl Bielefeldt
sumber
2
Contoh penting lainnya adalah CPython. Kode ini menggunakan banyak konsep OOP namun 100% murni C.
Bakuriu
@ Bakuriu Saya pikir Anda membingungkan Cython dan CPython
cat
1
@cat Dia mungkin berarti API Python C, Cython tidak 100% murni C. docs.python.org/c-api/intro.html
JAB
5
@cat No. Lihat sumber CPython. Sebagian besar hal memang dilakukan dengan menggunakan paradigma OOP, dan mereka menyediakan OOP API yang sebagian besar cocok dengan API python.
Bakuriu
1
@ Bakuriu Oh, maksud Anda runtime, sumber, dan API C Python bukan bahasa Python. komentar Anda tidak memperjelas hal itu
kucing
8

Dengan pointer fungsi, Anda dapat melakukan:

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

Ini umumnya hanya berguna jika implementasi dapat berubah, dalam hal ini Anda harus menggunakan vtable sehingga overhead hanya satu pointer per struct:

str.vtable->replace(&str, i, c);
o11c
sumber
3
Saya cenderung masih menyebutnya sebagai string_replace (& str, i, c) kemudian menggunakan vtable di dalam string_replace daripada meminta situs panggilan tahu tentang vtable.
Pete Kirkham
2
@Pete Nama yang dimulai dengan str(atau mematau wcs) dan huruf kecil dicadangkan oleh standar C untuk ekstensi di masa mendatang, jadi jangan menyebutnya string_replace. str_replacebaik-baik saja.
David Conrad
3

Ya, mereka bisa, semacam. Anda dapat menggunakan fakta bahwa C memungkinkan pointer berfungsi blok di memori, alias fungsi pointer dan menggunakan bahwa Anda dapat membuat antarmuka seperti polimorfisme serta fungsi virtual (bahkan jika tidak begitu cantik).

Saya menulis posting blog tentang hal ini, mengikuti pertanyaan dari salah satu siswa saya, baru-baru ini, yang berkaitan dengan kode seperti antarmuka dalam C dan Go, Anda dapat membacanya di sini:

Posting blog pada antarmuka non-OO

Lihat apakah itu memberi Anda ide.

Anda juga bisa memasukkan fungsi bebas ke dalam kode Anda, dan menggunakan penunjuk "this", yang berarti Anda meneruskan sebuah pointer ke struct yang sudah ada untuk dikerjakan, seperti dijelaskan dalam jawaban lain.

Richard Tyregrim
sumber