Apa sajakah cara untuk menulis kode berorientasi objek dalam C? Terutama berkenaan dengan polimorfisme.
Lihat juga ini Stack Overflow pertanyaan Obyek-orientasi dalam C .
Apa sajakah cara untuk menulis kode berorientasi objek dalam C? Terutama berkenaan dengan polimorfisme.
Lihat juga ini Stack Overflow pertanyaan Obyek-orientasi dalam C .
Jawaban:
Iya. Bahkan Axel Schreiner menyediakan bukunya "Pemrograman Berorientasi Objek dalam ANSI-C" secara gratis yang mencakup subjek cukup menyeluruh.
sumber
Karena Anda berbicara tentang polimorfisme maka ya, Anda bisa, kami melakukan hal-hal semacam itu bertahun-tahun sebelum C ++ muncul.
Pada dasarnya Anda menggunakan a
struct
untuk menyimpan data dan daftar pointer fungsi untuk menunjuk ke fungsi yang relevan untuk data tersebut.Jadi, di kelas komunikasi, Anda akan memiliki panggilan terbuka, baca, tulis, dan tutup yang akan dipertahankan sebagai empat fungsi pointer dalam struktur, di samping data untuk objek, seperti:
Tentu saja, segmen kode tersebut di atas sebenarnya akan berada dalam "konstruktor" seperti
rs232Init()
.Ketika Anda 'mewarisi' dari kelas itu, Anda hanya mengubah pointer untuk menunjuk ke fungsi Anda sendiri. Setiap orang yang memanggil fungsi-fungsi itu akan melakukannya melalui pointer fungsi, memberi Anda polimorfisme Anda:
Semacam seperti vtable manual.
Anda bahkan bisa memiliki kelas virtual dengan mengatur pointer ke NULL -perilaku akan sedikit berbeda dengan C ++ (core dump pada saat run-time daripada kesalahan pada waktu kompilasi).
Berikut sepotong kode contoh yang menunjukkannya. Pertama struktur kelas tingkat atas:
Kemudian kita memiliki fungsi untuk TCP 'subclass':
Dan HTTP juga:
Dan akhirnya program uji untuk menunjukkannya dalam aksi:
Ini menghasilkan output:
sehingga Anda dapat melihat bahwa fungsi yang berbeda sedang dipanggil, tergantung pada sub-kelas.
sumber
tCommClass
akan diubah namanya menjaditCommVT
, dantCommClass
struct hanya akan memiliki bidang data dan bidang tunggal yangtCommVT vt
menunjuk ke "satu-satunya" tabel virtual. Membawa semua petunjuk dengan setiap contoh menambahkan overhead yang tidak perlu dan lebih menyerupai bagaimana Anda akan melakukan hal-hal dalam JavaScript daripada C ++, IMHO.Ruang nama sering dilakukan dengan melakukan:
dari pada
Untuk membuat C struct menjadi sesuatu seperti kelas C ++ Anda dapat mengubah:
Ke
Dan lakukan:
Saya tidak melakukan destruktor atau menghapus, tetapi mengikuti pola yang sama.
this_is_here_as_an_example_only seperti variabel kelas statis - dibagikan di antara semua contoh jenis. Semua metode benar-benar statis, kecuali ada yang mengambil ini *
sumber
st->my_type->push(st, thing2);
bukanst->my_type.push(st, thing2);
struct stack_type my_type;
bukannyastruct stack_type * my_type;
Class
struct generik ? Itu akan membuat OO C lebih dinamis daripada C ++. Bagaimana tentang itu? Omong-omong, +1.Saya percaya bahwa selain berguna dalam haknya sendiri, menerapkan OOP dalam C adalah cara terbaik untuk mempelajari OOP dan memahami cara kerja bagian dalamnya. Pengalaman banyak programmer telah menunjukkan bahwa untuk menggunakan teknik secara efisien dan percaya diri, seorang programmer harus memahami bagaimana konsep-konsep yang mendasarinya akhirnya diimplementasikan. Meniru kelas, warisan, dan polimorfisme dalam C mengajarkan hal ini.
Untuk menjawab pertanyaan awal, berikut adalah beberapa sumber yang mengajarkan bagaimana melakukan OOP di C:
Posting blog EmbeddedGurus.com "Pemrograman berbasis objek dalam C" menunjukkan bagaimana mengimplementasikan kelas dan pewarisan tunggal dalam C portabel: http://embeddedgurus.com/state-space/2008/01/object-based-programming-in-c /
Catatan Aplikasi "" C + "- Pemrograman Berorientasi Objek dalam C" menunjukkan bagaimana mengimplementasikan kelas, pewarisan tunggal, dan pengikatan akhir (polimorfisme) dalam C menggunakan macro preprocessor: http://www.state-machine.com/resources/cplus_3. 0_manual.pdf , kode contoh tersedia dari http://www.state-machine.com/resources/cplus_3.0.zip
sumber
Saya sudah melihatnya selesai. Saya tidak akan merekomendasikannya. C ++ awalnya dimulai dengan cara ini sebagai preprosesor yang menghasilkan kode C sebagai langkah perantara.
Pada dasarnya apa yang Anda akhirnya lakukan adalah membuat tabel pengiriman untuk semua metode Anda di mana Anda menyimpan referensi fungsi Anda. Turunnya kelas akan memerlukan menyalin tabel pengiriman ini dan mengganti entri yang ingin Anda timpa, dengan "metode" baru Anda harus memanggil metode asli jika ingin memanggil metode dasar. Akhirnya, Anda akhirnya menulis ulang C ++.
sumber
glib
ditulis dalam C dengan cara yang objektif?Yakin itu mungkin. Inilah yang dilakukan GObject , kerangka kerja yang mendasari semua GTK + dan GNOME .
sumber
Sub-pustaka C stdio FILE adalah contoh yang sangat baik tentang cara membuat abstraksi, enkapsulasi, dan modularitas dalam C. yang tidak disadap.
Warisan dan polimorfisme - aspek-aspek lain yang sering dianggap penting untuk OOP - tidak selalu memberikan keuntungan produktivitas yang mereka janjikan dan argumen yang masuk akal telah dibuat bahwa mereka benar-benar dapat menghambat perkembangan dan berpikir tentang domain masalah.
sumber
Contoh sepele dengan Hewan dan Anjing: Anda mencerminkan mekanisme vtable C ++ (sebagian besar toh). Anda juga memisahkan alokasi dan instantiasi (Animal_Alloc, Animal_New) sehingga kami tidak memanggil malloc () beberapa kali. Kita juga harus secara eksplisit melewatkan
this
pointer.Jika Anda melakukan fungsi non-virtual, itu trival. Anda hanya tidak menambahkannya ke fungsi vtable dan statis tidak memerlukan
this
pointer. Multiple inheritance umumnya membutuhkan banyak vtables untuk menyelesaikan ambiguitas.Selain itu, Anda harus dapat menggunakan setjmp / longjmp untuk melakukan penanganan pengecualian.
PS. Ini diuji pada kompiler C ++, tetapi harus mudah membuatnya bekerja pada kompiler C.
sumber
typedef
di dalamstruct
tidak dimungkinkan dalam C.Lihat GObject . Ini dimaksudkan sebagai OO dalam C dan satu implementasi dari apa yang Anda cari. Jika Anda benar-benar menginginkan OO, gunakan C ++ atau bahasa OOP lainnya. GObject terkadang bisa sangat sulit untuk digunakan jika Anda terbiasa berurusan dengan bahasa OO, tetapi seperti apa pun, Anda akan terbiasa dengan konvensi dan aliran.
sumber
Ini menarik untuk dibaca. Saya sendiri telah memikirkan pertanyaan yang sama, dan manfaat dari memikirkannya adalah ini:
Mencoba membayangkan bagaimana menerapkan konsep OOP dalam bahasa non-OOP membantu saya memahami kekuatan bahasa OOp (dalam kasus saya, C ++). Ini membantu memberi saya penilaian yang lebih baik tentang apakah akan menggunakan C atau C ++ untuk jenis aplikasi yang diberikan - di mana manfaat dari satu lebih besar dari yang lain.
Dalam menjelajah web saya untuk informasi dan pendapat tentang ini, saya menemukan seorang penulis yang sedang menulis kode untuk prosesor tertanam dan hanya memiliki kompiler C yang tersedia: http://www.eetimes.com/discussion/other/4024626/Object-Oriented -C-Menciptakan-Yayasan-Kelas-Bagian-1
Dalam kasusnya, menganalisis dan mengadaptasi konsep OOP di dataran C adalah pengejaran yang valid. Tampaknya ia terbuka untuk mengorbankan beberapa konsep OOP karena hit overhead kinerja yang dihasilkan dari upaya untuk mengimplementasikannya dalam C.
Pelajaran yang saya ambil adalah, ya itu bisa dilakukan sampai tingkat tertentu, dan ya, ada beberapa alasan bagus untuk mencobanya.
Pada akhirnya, mesin memutar-mutar bit pointer stack, membuat penghitung program melompat-lompat dan menghitung operasi akses memori. Dari sudut pandang efisiensi, semakin sedikit perhitungan yang dilakukan oleh program Anda, semakin baik ... tetapi terkadang kami harus membayar pajak ini hanya agar kami dapat mengatur program kami dengan cara yang membuatnya paling tidak rentan terhadap kesalahan manusia. Kompilator bahasa OOP berusaha untuk mengoptimalkan kedua aspek. Programmer harus lebih berhati-hati mengimplementasikan konsep-konsep ini dalam bahasa seperti C.
sumber
Anda mungkin terbantu untuk melihat dokumentasi Apple untuk kumpulan Core Foundation-nya. Ini adalah API C murni, tetapi banyak tipe yang dijembatani dengan objek Objective-C yang setara.
Anda juga mungkin merasa terbantu untuk melihat desain Objective-C itu sendiri. Ini sedikit berbeda dari C ++ karena sistem objek didefinisikan dalam hal fungsi C, misalnya
objc_msg_send
untuk memanggil metode pada objek. Kompiler menerjemahkan sintaks braket kuadrat ke dalam panggilan fungsi tersebut, jadi Anda tidak perlu mengetahuinya, tetapi mempertimbangkan pertanyaan Anda, Anda mungkin menemukan manfaatnya untuk mempelajari cara kerjanya di bawah tenda.sumber
Ada beberapa teknik yang bisa digunakan. Yang paling penting adalah bagaimana membagi proyek. Kami menggunakan antarmuka dalam proyek kami yang dideklarasikan dalam file .h dan implementasi objek dalam file .c. Bagian yang penting adalah bahwa semua modul yang menyertakan file .h hanya melihat objek sebagai
void *
, dan file .c adalah satu-satunya modul yang mengetahui internal struktur.Sesuatu seperti ini untuk kelas yang kita beri nama FOO sebagai contoh:
Dalam file .h
File implementasi C akan seperti itu.
Jadi saya memberikan pointer secara eksplisit ke objek ke setiap fungsi modul itu. Kompiler C ++ melakukannya secara implisit, dan dalam C kita menuliskannya secara eksplisit.
Saya sangat menggunakan
this
dalam program saya, untuk memastikan bahwa program saya tidak dikompilasi dalam C ++, dan itu memiliki sifat yang baik berada dalam warna lain di editor menyoroti sintaks saya.Bidang-bidang FOO_struct dapat dimodifikasi dalam satu modul dan modul lainnya bahkan tidak perlu dikompilasi ulang agar tetap dapat digunakan.
Dengan gaya itu saya sudah menangani sebagian besar keunggulan OOP (enkapsulasi data). Dengan menggunakan pointer fungsi, itu bahkan mudah untuk mengimplementasikan sesuatu seperti warisan, tetapi jujur, itu benar-benar jarang berguna.
sumber
typedef struct FOO_type FOO_type
alih - alih mengetikkan membatalkan di header Anda mendapatkan manfaat tambahan dari pemeriksaan jenis, sementara masih tidak mengekspos struktur Anda.Anda dapat memalsunya menggunakan pointer fungsi, dan pada kenyataannya, saya pikir secara teori dimungkinkan untuk mengkompilasi program C ++ ke C.
Namun, jarang masuk akal untuk memaksakan paradigma pada suatu bahasa daripada memilih bahasa yang menggunakan paradigma.
sumber
Berorientasi objek C, dapat dilakukan, saya telah melihat jenis kode dalam produksi di Korea, dan itu adalah monster paling mengerikan yang pernah saya lihat selama bertahun-tahun (ini seperti tahun lalu (2007) yang saya lihat kode). Jadi ya itu bisa dilakukan, dan ya orang sudah melakukannya sebelumnya, dan masih melakukannya bahkan di zaman sekarang ini. Tapi saya akan merekomendasikan C ++ atau Objective-C, keduanya bahasa yang lahir dari C, dengan tujuan memberikan orientasi objek dengan paradigma yang berbeda.
sumber
Jika Anda yakin bahwa pendekatan OOP lebih unggul untuk masalah yang Anda coba selesaikan, mengapa Anda mencoba menyelesaikannya dengan bahasa non-OOP? Sepertinya Anda menggunakan alat yang salah untuk pekerjaan itu. Gunakan C ++ atau bahasa varian C berorientasi objek lainnya.
Jika Anda bertanya karena Anda mulai membuat kode pada proyek besar yang sudah ada yang ditulis dalam C, maka Anda tidak boleh mencoba memaksakan paradigma OOP Anda sendiri (atau orang lain) ke dalam infrastruktur proyek. Ikuti panduan yang sudah ada dalam proyek. Secara umum, API bersih dan terisolasi perpustakaan dan modul akan pergi jauh ke arah memiliki bersih OOP- ish desain.
Jika, setelah semua ini, Anda benar-benar siap melakukan OOP C, baca ini (PDF).
sumber
Ya kamu bisa. Orang-orang menulis berorientasi objek C sebelum C ++ atau Objective-C muncul. Baik C ++ dan Objective-C, sebagian, berupaya untuk mengambil beberapa konsep OO yang digunakan dalam C dan memformalkannya sebagai bagian dari bahasa.
Berikut adalah program yang sangat sederhana yang menunjukkan bagaimana Anda dapat membuat sesuatu yang terlihat seperti / adalah pemanggilan metode (ada cara yang lebih baik untuk melakukan ini. Ini hanya bukti bahwa bahasa mendukung konsep-konsep):
sumber
Tentu saja, itu tidak akan secantik menggunakan bahasa dengan dukungan bawaan. Saya bahkan sudah menulis "assembler berorientasi objek".
sumber
Sedikit kode OOC untuk ditambahkan:
sumber
Saya telah menggali ini selama satu tahun:
Karena sistem GObject sulit digunakan dengan C murni, saya mencoba menulis beberapa makro bagus untuk meringankan gaya OO dengan C.
Ini situs proyek saya (saya tidak punya cukup waktu untuk menulis en. Doc, namun doc dalam bahasa Cina jauh lebih baik).
OOC-GCC
sumber
Ada contoh pewarisan menggunakan C dalam ceramah Jim Larson 1996 yang diberikan pada Bagian 312 Seminar Pemrograman Makan Siang di sini: C Tinggi dan Rendah .
sumber
Dave Hanson C Interfaces dan Implementasi adalah sangat baik pada enkapsulasi dan penamaan dan sangat baik pada penggunaan fungsi pointer. Dave tidak mencoba mensimulasikan pewarisan.
sumber
OOP hanyalah paradigma yang menempatkan data lebih penting daripada kode dalam program. OOP bukan bahasa. Jadi, seperti plain C adalah bahasa yang sederhana, OOP dalam plain C juga sederhana.
sumber
Satu hal yang mungkin ingin Anda lakukan adalah melihat implementasi Xt toolkit untuk X Window . Memang sudah lama di gigi, tetapi banyak struktur yang digunakan dirancang untuk bekerja secara OO dalam C. tradisional. Umumnya ini berarti menambahkan lapisan tipuan tambahan di sana-sini dan merancang struktur untuk saling menempel.
Anda benar-benar dapat melakukan banyak hal di jalan OO yang terletak di C dengan cara ini, meskipun terasa seperti itu beberapa kali, konsep OO tidak muncul sepenuhnya dari pikiran
#include<favorite_OO_Guru.h>
. Mereka benar-benar merupakan banyak praktik terbaik yang ada saat itu. Bahasa dan sistem OO hanya menyaring dan memperkuat bagian-bagian dari zeitgeist pemrograman saat itu.sumber
Jawaban untuk pertanyaan itu adalah 'Ya, Anda bisa'.
Object-oriented C (OOC) kit adalah untuk mereka yang ingin memprogram dengan cara berorientasi objek, tetapi tetap menggunakan C lama yang baik juga. OOC mengimplementasikan kelas, pewarisan tunggal dan ganda, penanganan pengecualian.
fitur
• Hanya menggunakan makro C dan fungsi, tidak perlu ekstensi bahasa! (ANSI-C)
• Kode sumber yang mudah dibaca untuk aplikasi Anda. Perawatan diambil untuk membuat hal-hal sesederhana mungkin.
• Warisan tunggal kelas
• Warisan berganda dengan antarmuka dan mixin (sejak versi 1.3)
• Menerapkan pengecualian (dalam C murni!)
• Fungsi virtual untuk kelas
• Alat eksternal untuk implementasi kelas yang mudah
Untuk detail lebih lanjut, kunjungi http://ooc-coding.sourceforge.net/ .
sumber
Sepertinya orang mencoba meniru gaya C ++ menggunakan C. Saya kira adalah melakukan pemrograman berorientasi objek C benar-benar melakukan pemrograman berorientasi-struktur. Namun, Anda dapat mencapai hal-hal seperti ikatan yang terlambat, enkapsulasi, dan pewarisan. Untuk warisan Anda secara eksplisit menentukan pointer ke struct dasar di sub struct Anda dan ini jelas merupakan bentuk multiple inheritance. Anda juga harus menentukan apakah Anda
kompilasi dengan
c_compiler main.c inherited_class_1.obj inherited_class_2.obj private_class.obj
.Jadi sarannya adalah tetap berpegang pada gaya C murni dan tidak mencoba memaksakan gaya C ++. Juga cara ini cocok untuk cara yang sangat bersih untuk membangun API.
sumber
Lihat http://slkpg.byethost7.com/instance.html untuk twist lain pada OOP di C. Ini menekankan contoh data untuk reentrancy menggunakan hanya asli C. Banyak warisan dilakukan secara manual menggunakan pembungkus fungsi. Keamanan jenis dipertahankan. Ini adalah contoh kecil:
sumber
Saya agak terlambat ke pesta, tapi saya ingin berbagi pengalaman saya tentang topik: Saya bekerja dengan hal-hal yang disematkan hari ini, dan satu-satunya kompiler (dapat diandalkan) yang saya miliki adalah C, sehingga saya ingin menerapkan berorientasi objek pendekatan dalam proyek tertanam saya ditulis dalam C.
Sebagian besar solusi yang saya lihat sejauh ini banyak menggunakan typecast, jadi kami kehilangan keamanan jenis: kompiler tidak akan membantu Anda jika Anda melakukan kesalahan. Ini benar-benar tidak dapat diterima.
Persyaratan yang saya miliki:
Saya telah menjelaskan pendekatan saya secara rinci dalam artikel ini: Pemrograman berorientasi objek dalam C ; ditambah, ada utilitas untuk autogenerasi kode boilerplate untuk kelas dasar dan turunan.
sumber
Saya membangun perpustakaan kecil tempat saya mencobanya dan bagi saya itu berfungsi dengan baik. Jadi saya pikir saya berbagi pengalaman.
https://github.com/thomasfuhringer/oxygen
Warisan tunggal dapat diimplementasikan dengan cukup mudah menggunakan struct dan memperluasnya untuk setiap kelas anak lainnya. Gips sederhana ke struktur induk memungkinkan untuk menggunakan metode induk pada semua keturunan. Selama Anda tahu bahwa sebuah variabel menunjuk ke sebuah struct yang memegang objek semacam ini, Anda selalu dapat melakukan cast ke kelas root dan melakukan introspeksi.
Seperti yang telah disebutkan, metode virtual agak rumit. Tapi itu bisa dilakukan. Untuk menjaga hal-hal sederhana, saya hanya menggunakan array fungsi dalam struktur deskripsi kelas yang setiap kelas anak menyalin dan mengisi kembali slot individu di mana diperlukan.
Berbagai warisan akan agak rumit untuk diterapkan dan disertai dengan dampak kinerja yang signifikan. Jadi saya tinggalkan saja. Saya menganggap itu diinginkan dan berguna dalam beberapa kasus untuk memodelkan keadaan kehidupan nyata dengan bersih, tetapi mungkin 90% dari kasus warisan tunggal mencakup kebutuhan. Dan warisan tunggal itu sederhana dan tidak ada biaya.
Juga saya tidak peduli tentang keamanan tipe. Saya pikir Anda tidak harus bergantung pada kompiler untuk mencegah Anda dari kesalahan pemrograman. Dan itu melindungi Anda hanya dari sebagian kecil kesalahan saja.
Biasanya, dalam lingkungan berorientasi objek Anda juga ingin menerapkan penghitungan referensi untuk mengotomatisasi manajemen memori sejauh mungkin. Jadi saya juga memasukkan jumlah referensi ke kelas root "Object" dan beberapa fungsionalitas untuk merangkum alokasi dan deallokasi memori heap.
Itu semua sangat sederhana dan ramping dan memberi saya esensi OO tanpa memaksa saya untuk berurusan dengan monster yang C ++. Dan saya mempertahankan fleksibilitas untuk tinggal di tanah C, yang antara lain membuatnya lebih mudah untuk mengintegrasikan perpustakaan pihak ketiga.
sumber
Saya mengusulkan untuk menggunakan Objective-C, yang merupakan superset dari C.
Sementara Objective-C berusia 30 tahun, memungkinkan untuk menulis kode yang elegan.
http://en.wikipedia.org/wiki/Objective-C
sumber
Ya, tapi saya belum pernah melihat orang yang mencoba menerapkan polimorfisme apa pun dengan C.
sumber