Saya mencoba memahami perbedaan antara bahasa prosedural seperti C dan bahasa berorientasi objek seperti C ++. Saya tidak pernah menggunakan C ++, tetapi saya telah berdiskusi dengan teman-teman saya tentang cara membedakan keduanya.
Saya telah diberi tahu C ++ memiliki konsep berorientasi objek serta mode publik dan pribadi untuk definisi variabel: hal-hal yang tidak dimiliki C. Saya belum pernah menggunakan ini untuk saat mengembangkan program dalam Visual Basic.NET: apa manfaatnya?
Saya juga telah diberitahu bahwa jika suatu variabel bersifat publik, ia dapat diakses di mana saja, tetapi tidak jelas bagaimana hal itu berbeda dari variabel global dalam bahasa seperti C. Juga tidak jelas bagaimana variabel pribadi berbeda dari variabel lokal.
Hal lain yang saya dengar adalah bahwa, untuk alasan keamanan, jika suatu fungsi perlu diakses, itu harus diwarisi terlebih dahulu. Kasus penggunaannya adalah bahwa seorang administrator hanya boleh memiliki hak sebanyak yang mereka butuhkan dan bukan segalanya, tetapi tampaknya persyaratan juga akan berfungsi:
if ( login == "admin") {
// invoke the function
}
Mengapa ini tidak ideal?
Mengingat bahwa tampaknya ada cara prosedural untuk melakukan segala sesuatu yang berorientasi objek, mengapa saya harus peduli tentang pemrograman berorientasi objek?
sumber
Jawaban:
Semua jawaban sejauh ini berfokus pada topik pertanyaan Anda sebagaimana dinyatakan, yaitu "apa perbedaan antara c dan c ++". Pada kenyataannya, sepertinya Anda tahu apa perbedaannya, Anda hanya tidak mengerti mengapa Anda membutuhkan perbedaan itu. Maka, jawaban lain berusaha menjelaskan OO dan enkapsulasi.
Saya ingin menjawab dengan jawaban lain, karena berdasarkan perincian pertanyaan Anda, saya yakin Anda perlu mengambil beberapa langkah kembali.
Anda tidak mengerti tujuan C ++ atau OO, karena bagi Anda, tampaknya aplikasi Anda hanya perlu menyimpan data. Data ini disimpan dalam variabel. "Mengapa saya ingin membuat variabel tidak dapat diakses? Sekarang saya tidak dapat mengaksesnya lagi! Dengan membuat semuanya menjadi publik, atau lebih baik secara global, saya dapat membaca data dari mana saja dan tidak ada masalah." - Dan Anda benar, berdasarkan skala proyek yang sedang Anda tulis, mungkin tidak banyak masalah (atau ada, tetapi Anda belum menyadarinya).
Saya pikir pertanyaan mendasar yang benar-benar perlu Anda jawab adalah: "Mengapa saya ingin menyembunyikan data? Jika saya melakukan itu, saya tidak bisa mengatasinya!" Dan inilah sebabnya:
Katakanlah Anda memulai proyek baru, Anda membuka editor teks Anda dan Anda mulai menulis fungsi. Setiap kali Anda perlu menyimpan sesuatu (untuk mengingatnya nanti), Anda membuat variabel. Untuk mempermudah, Anda membuat variabel Anda mendunia. Versi pertama aplikasi Anda berjalan sangat baik. Sekarang Anda mulai menambahkan lebih banyak fitur. Anda memiliki lebih banyak fungsi, data tertentu yang Anda simpan sebelumnya perlu dibaca dari kode baru Anda. Variabel lain perlu dimodifikasi. Anda terus menulis lebih banyak fungsi. Apa yang mungkin Anda perhatikan (atau, jika tidak, Anda benar-benar akan melihat di masa depan) adalah, karena kode Anda semakin besar, Anda butuh waktu lebih lama untuk menambahkan fitur berikutnya. Dan saat kode Anda semakin besar, semakin sulit untuk menambahkan fitur tanpa merusak sesuatu yang dulu berfungsi. Mengapa? Karena kamu perlu mengingat semuanyavariabel global Anda disimpan dan Anda harus mengingat di mana semuanya sedang dimodifikasi. Dan Anda perlu mengingat fungsi mana yang boleh memanggil dalam urutan yang tepat dan jika Anda memanggilnya dalam urutan yang berbeda , Anda mungkin mendapatkan kesalahan karena variabel global Anda belum cukup valid. Apakah Anda pernah mengalami ini?
Seberapa besar proyek khas Anda (garis kode)? Sekarang pencitraan proyek 5000 hingga 50.000 kali lebih besar dari proyek Anda. Juga, ada beberapa orang yang bekerja di dalamnya. Bagaimana semua orang di tim dapat mengingat (atau bahkan menyadari) apa yang dilakukan semua variabel itu?
Apa yang saya jelaskan di atas adalah contoh kode yang digabungkan dengan sempurna. Dan sejak awal waktu (dengan asumsi waktu mulai 1 Januari 1970), manusia telah mencari cara untuk menghindari masalah ini. Cara Anda menghindarinya adalah dengan memecah kode Anda menjadi sistem, subsistem, dan komponen dan membatasi berapa banyak fungsi yang memiliki akses ke bagian data apa pun. Jika saya memiliki 5 bilangan bulat dan sebuah string yang mewakili semacam keadaan, apakah akan lebih mudah bagi saya untuk bekerja dengan keadaan ini jika hanya 5 fungsi yang mengatur / mendapatkan nilai? atau jika 100 fungsi mengatur / mendapatkan nilai yang sama? Bahkan tanpa bahasa OO (yaitu C), orang-orang telah bekerja keras untuk mengisolasi data dari data lain dan menciptakan batas pemisahan yang bersih antara berbagai bagian kode. Ketika proyek mencapai ukuran tertentu, kemudahan pemrograman menjadi tidak, "bisakah saya mengakses variabel X dari fungsi Y",
Inilah sebabnya mengapa konsep OO telah diperkenalkan dan inilah mengapa mereka begitu kuat. Mereka memungkinkan Anda untuk menyembunyikan data dari diri Anda sendiri dan Anda ingin melakukannya dengan sengaja, karena semakin sedikit kode yang melihat data itu, semakin sedikit kesempatan ada, bahwa ketika Anda menambahkan fitur berikutnya, Anda akan merusak sesuatu. Ini adalah tujuan utama untuk konsep enkapsulasi dan pemrograman OO. Mereka memungkinkan Anda untuk memecah sistem / subsistem kami menjadi kotak yang lebih terperinci, ke titik di mana, tidak peduli seberapa besar keseluruhan proyek, sekumpulan variabel tertentu hanya dapat diakses oleh 50-200 baris kode dan hanya itu! Jelas ada jauh lebih banyak untuk pemrograman OO, tetapi, pada dasarnya, inilah sebabnya C ++ memberi Anda pilihan untuk mendeklarasikan data / fungsi sebagai pribadi, dilindungi atau publik.
Ide terbesar kedua dalam OO adalah konsep lapisan abstraksi. Meskipun bahasa prosedural juga dapat memiliki abstraksi, dalam C, seorang programmer harus melakukan upaya sadar untuk membuat lapisan seperti itu, tetapi dalam C ++, ketika Anda mendeklarasikan sebuah kelas, Anda secara otomatis membuat lapisan abstraksi (itu masih terserah Anda apakah abstraksi ini atau tidak) akan menambah atau menghapus nilai). Anda harus membaca / meneliti lebih lanjut tentang lapisan abstraksi dan jika Anda memiliki lebih banyak pertanyaan, saya yakin forum ini akan dengan senang hati menjawabnya juga.
sumber
Hmm ... mungkin yang terbaik adalah membuat cadangan dan mencoba memberikan beberapa gagasan tentang maksud dasar pemrograman berorientasi objek. Sebagian besar tujuan pemrograman berorientasi objek adalah untuk memungkinkan penciptaan tipe data abstrak. Untuk contoh yang sangat sederhana yang Anda tidak asing lagi, pertimbangkan string. Sebuah string biasanya memiliki buffer untuk menampung konten string, beberapa fungsi yang dapat beroperasi pada string (mencari di dalamnya, mengakses bagian-bagiannya, membuat substring, dll.) Itu juga akan (setidaknya biasanya) memiliki sesuatu untuk melacak panjang string (saat ini), dan (mungkin) ukuran buffer jadi jika (misalnya) Anda menambah ukuran string dari 1 menjadi 10.00000, ia akan tahu kapan perlu lebih banyak memori untuk menahan yang lebih besar konten.
Variabel-variabel tersebut (buffer, panjang saat ini dan ukuran buffer) bersifat pribadi untuk string itu sendiri, tetapi mereka tidak lokal untuk fungsi tertentu. Setiap string memiliki konten dengan panjang tertentu, jadi kita perlu melacak konten / panjang untuk string itu. Sebaliknya, fungsi yang sama (misalnya, untuk mengekstraksi substring) dapat beroperasi pada banyak string berbeda pada waktu yang berbeda, sehingga data tidak dapat lokal ke fungsi individu.
Dengan demikian, kita berakhir dengan beberapa data yang bersifat pribadi untuk string, sehingga hanya (langsung) dapat diakses oleh fungsi string. Dunia luar bisa mendapatkan panjang string menggunakan fungsi string, tetapi tidak perlu tahu apa-apa tentang internal string untuk mendapatkannya. Demikian juga, mungkin memodifikasi string - tetapi sekali lagi, ia melakukannya melalui fungsi string, dan hanya mereka yang secara langsung memodifikasi variabel-variabel lokal ke objek string.
Sejauh keamanan berjalan, saya perhatikan bahwa sementara ini masuk akal sebagai analogi, itu bukan cara kerja yang sebenarnya. Secara khusus, akses dalam C ++ secara khusus tidak dimaksudkan untuk memenuhi jenis persyaratan yang sama dengan akses dalam sistem operasi. Sistem operasi seharusnya menerapkan pembatasan sehingga (misalnya) pengguna normal tidak dapat melakukan hal-hal yang disediakan untuk administrator. Sebaliknya, kontrol akses di C ++ hanya dimaksudkan untuk mencegah kecelakaan. Secara desain, siapa pun yang ingin dapat mem-bypass mereka dengan mudah. Mereka berada di urutan yang sama dengan menandai file hanya-baca sehingga Anda tidak sengaja menghapusnya. Jika Anda memutuskan untuk menghapus file, itu sepele untuk mengubahnya dari read-only menjadi read-write; semua pengaturan untuk hanya-baca tidak membuat Anda setidaknya memikirkannya sebentar dan memutuskan untuk menghapus file sehingga tidak akan terhapus secara tidak sengaja hanya dari menekan tombol yang salah pada waktu yang salah.
sumber
OOP versus C sebenarnya bukan tentang hal-hal yang telah Anda diskusikan. Ini terutama tentang pengemasan kode ke area yang tidak akan / tidak bisa tidak sengaja (atau kadang-kadang bahkan dengan sengaja) saling mempengaruhi.
C memungkinkan Anda menjalankan fungsi apa pun dari mana saja. OOP mencegahnya dengan mengelompokkan metode ke dalam kelas dan hanya memungkinkan Anda untuk menggunakan metode dengan merujuk kelas yang mengandungnya. Jadi, salah satu keuntungan OOP yang potensial adalah bahwa Anda jauh lebih mungkin memiliki pengaturan kode yang lebih baik tanpa banyak pengalaman untuk memberi tahu Anda bahwa Anda harus melakukannya.
sumber
Kelas yang ditulis dengan baik harus menjadi "pulau kepercayaan" kecil: Anda dapat menggunakannya dan menganggap bahwa itu "hal yang benar" dan bahwa ia melindungi Anda dari perangkap umum. Itu membuat kelas yang bagus sebagai blok bangunan, yang jauh lebih dapat digunakan kembali sebagai sekelompok fungsi dan variabel, yang mungkin bekerja dengan baik tetapi menunjukkan kepada Anda semua nyali jeleknya, dan memaksa Anda untuk memahami bagaimana mereka bekerja bersama, bagaimana mereka perlu diinisialisasi dll. Kelas yang baik harus seperti colokan USB, sedangkan solusi prosedural seperti sekelompok kabel, keripik, timah dan sedikit solder.
Satu hal yang tidak dibahas secara mendalam adalah aspek antarmuka / implementasi. Antarmuka menggambarkan perilaku, tetapi bukan realisasinya. Jadi daftar antarmuka menggambarkan konsep tersebutdaftar dan perilakunya: Anda akan mengharapkan hal-hal seperti menambahkan, menghapus dan metode ukuran. Sekarang ada banyak cara berbeda untuk mengimplementasikan daftar ini, misalnya sebagai daftar tertaut atau menggunakan buffer array. Kekuatan dari pemrograman OO adalah bahwa dengan menggunakan antarmuka Anda dapat alasan tentang perilaku tanpa mengetahui tentang implementasinya. Mengakses variabel atau metode internal akan menghancurkan abstraksi ini, Anda tidak bisa mengganti satu implementasi daftar dengan yang lain, dan Anda tidak bisa meningkatkan implementasi yang ada tanpa menyentuh kode menggunakan kelas. Itulah salah satu alasan utama mengapa variabel dan metode pribadi diperlukan: Untuk melindungi detail internal dari implementasi, sehingga abstraksi tetap utuh.
OO bahkan melangkah lebih jauh: Misalnya untuk perpustakaan Anda dapat mendefinisikan antarmuka untuk hal-hal yang bahkan belum ada , dan menulis kode yang berfungsi dengan antarmuka itu. Pengguna dapat menulis kelas yang mengimplementasikan antarmuka, dan menggunakan layanan yang disediakan oleh perpustakaan. Ini memungkinkan tingkat fleksibilitas yang tidak mungkin dengan pemrograman prosedural.
sumber
SetLocation
dapat digunakan untuk memindahkanMonster
, sementaraSetPosition
mungkin memindahkanPopupWindow
, danMove
mungkin digunakan untuk menyesuaikan posisi dari aDisplayCursor
). Mencoba menemukan metode "langkah" yang tepat ...MyMonstor->
editor hanya memperlihatkan daftar metode yang dapat diterapkan pada hal-hal yang bertipeMonster
. Jika ada banyak lusinan hal yang berbeda, masing-masing mendukung sekitar selusin operasi, mengurangi jumlah kekacauan dalam daftar metode hingga 90% dapat sangat mengurangi produktivitas.it
tipeSuperFancyWhizBang
, menjalankan salah satuSuperFancyWhizBang
metode diit
tidak memerlukan penulisan tipeSuperFancyWhizBang
; pepatahit.woozle()
akan mengarahkan kompiler untuk secara otomatis mencari diwoozle
dalamSuperFancyWhizBang
.Ada cara untuk melakukan semuanya dengan mesin Turing, atau setidaknya dalam bahasa assembly untuk kode mesin yang akhirnya dikompilasi oleh program C atau C ++.
Jadi perbedaannya bukan tentang apa yang bisa dilakukan kode, tetapi tentang apa yang bisa dilakukan orang.
Orang-orang membuat kesalahan. Banyak.
OOP memperkenalkan paradigma dan sintaksis yang membantu mengurangi ukuran dan kemungkinan kepadatan ruang dari kemungkinan kesalahan pengkodean manusia. Kadang-kadang dengan membuat kesalahan ilegal untuk kelas objek data tertentu (seperti itu bukan metode yang dideklarasikan untuk objek itu). Kadang-kadang dengan membuat kesalahan lebih verbose, atau terlihat aneh secara gaya dibandingkan dengan penggunaan bahasa secara kanonik. Kadang-kadang dengan membutuhkan antarmuka dengan penggunaan yang jauh lebih tidak mungkin atau terjerat (publik vs swasta). dll.
Semakin besar proyek, semakin tinggi kemungkinan kesalahan. Yang mana pembuat kode baru mungkin tidak terpapar jika hanya berpengalaman dengan program kecil. Dengan demikian potensi kebingungan mengapa OOP berharga.
sumber
Pertanyaan Anda tampaknya lebih tentang tujuan OOP daripada perbedaannya. Konsep dalam posting Anda adalah Enkapsulasi; dan enkapsulasi ada untuk mendukung CHANGE. Ketika kelas-kelas lain mengakses internal Anda, menjadi sulit untuk memodifikasinya tanpa merusaknya. Di OOP Anda menyediakan antarmuka (anggota publik) di mana Anda memungkinkan kelas lain untuk berinteraksi dengan Anda, dan Anda menyembunyikan internal Anda sehingga mereka dapat diubah dengan aman.
sumber
Saya harap Anda tidak pernah menginginkan lebih dari satu string dalam aplikasi Anda. Saya juga berharap bahwa variabel lokal Anda tetap ada di antara panggilan fungsi. Hal-hal ini mungkin sama dalam hal aksesibilitas tetapi dalam hal masa pakai dan penggunaan lainnya? Sama sekali tidak sama.
sumber
Seperti yang dikatakan banyak program, setelah dikompilasi, diubah menjadi kode biner dan, karena string biner dapat digunakan untuk mewakili integer, program apa pun pada akhirnya hanyalah angka. Namun mendefinisikan angka yang Anda butuhkan bisa sangat sulit dan itulah sebabnya bahasa pemrograman tingkat tinggi muncul. Bahasa pemrograman hanyalah model kode rakitan yang akhirnya mereka hasilkan. Saya ingin menjelaskan kepada Anda perbedaan antara pemrograman prosedural dan OO melalui makalah yang sangat bagus ini tentang Pemrograman Berorientasi Konteks http://www.jot.fm/issues/issue_2008_03/article4/
seperti yang Anda lihat dari gambar ini, digambarkan dalam makalah, pemrograman Prosedural hanya menyediakan satu dimensi untuk mengaitkan unit komputasi dengan nama. Di sini, panggilan prosedur atau nama dipetakan langsung ke implementasi prosedur. Pada Gambar-a, panggilan m1 tidak meninggalkan pilihan selain doa dari satu-satunya implementasi dari prosedur m1.
Pemrograman berorientasi objek menambahkan dimensi lain untuk resolusi nama ke pemrograman prosedural. Selain nama metode atau prosedur, pengiriman pesan mempertimbangkan penerima pesan ketika mencari metode. Pada Gambar-b kita melihat dua implementasi metode m1. Pemilihan metode yang tepat tidak hanya tergantung pada nama pesan m1, tetapi juga penerima pesan yang sebenarnya, di sini Ry.
Ini memang memungkinkan enkapsulasi dan modularisasi.
Gambar-c akhirnya tentang pemrograman berorientasi objek memperluas metode berorientasi objek pengiriman oleh dimensi lain.
Semoga ini membantu Anda berpikir di OOP dari perspektif yang berbeda.
sumber
(+1) Mengajukan pertanyaan tentang sesuatu yang tidak Anda mengerti, bagus, bahkan jika itu terdengar konyol.
Perbedaannya adalah Pemrograman Berorientasi Objek & Kelas. "Plain C", berfungsi dengan data & fungsi. "C ++" menambahkan konsep "objek & kelas", ditambah beberapa konsep sekunder terkait.
Namun, saya menganjurkan pengembang untuk mempelajari "Plain C" sebelum "C ++". Atau "Prosedural Pascal" sebelum "Object Pascal".
Banyak pengembang berpikir siswa seharusnya hanya mengajarkan satu hal.
Misalnya, guru lama yang tidak mendapatkan OO, dan hanya mengajar "Plain Structured C".
Atau "hipster" guru yang mengajar hanya OO, tetapi bukan "Plain C", karena "Anda tidak membutuhkannya". Atau keduanya, tanpa mempedulikan perintah mengajar.
Saya agak berpikir, siswa harus diajarkan "Structured Plain C" dan "Object Oriented C (C ++)". Dengan "Plain C", pertama, dan "C ++", nanti.
Di dunia nyata, Anda perlu mempelajari kedua paradigma (ditambah paradigma lain, seperti "fungsional").
Memikirkan program terstruktur sebagai "objek" besar, tunggal, dapat membantu.
Anda juga harus memberi penekanan pada ruang nama ("modul"), dalam kedua bahasa, banyak guru mengabaikannya, tetapi, ini penting.
sumber
foo()
di C ++, itu bisa menjadi fungsi global, fungsi di namespace saat ini, fungsi di namespace yang Anda gunakan denganusing
, metode, metode yang diwarisi dan jika ada di pemanggilan fungsi: itu bisa di namespace yang dapat diselesaikan dengan pencarian nama berbasis argumen, dan hal yang sama berlaku untuk Java dan C #. Dalam C itu hanya bisa menjadi fungsi statis di file sumber saat ini, atau satu dari header.Dalam satu kata, manajemen proyek. Maksud saya adalah bahwa C ++ membantu saya menegakkan aturan tentang bagaimana kode saya digunakan oleh orang lain. Bekerja pada proyek 5,5 juta baris saya menemukan pemrograman berorientasi objek sangat membantu. Keuntungan lain adalah kompiler yang membuat saya (dan orang lain) mengikuti aturan tertentu dan menangkap kesalahan kecil dalam waktu kompilasi. Semua keuntungan teoretis juga ada di sana, tetapi saya hanya ingin fokus pada hal-hal praktis sehari-hari. Setelah semua itu dikompilasi menjadi kode mesin.
sumber
Pemrograman Berorientasi Objek adalah Pemrograman Prosedural, dengan kotak-kotak.
Dalam PP, Anda memiliki satu kotak, satu keadaan, yang menjadi sangat besar ketika proyek tumbuh, menyebabkan efek samping muncul setiap kali Anda melupakan sedikit dari keadaan besar itu.
Di OO, Anda memiliki banyak kotak, banyak negara bagian, dan seiring proyek bertambah, kotak-kotak itu bertambah sedikit, dan jumlah kotak itu bertambah banyak.
Tetap lebih mudah untuk melihat kotak yang lebih kecil, mudah untuk memiliki ilusi seluruh gambar, tetapi sebenarnya hampir tidak mungkin, karena melihat kelas dan antarmuka menyembunyikan detail implementasi yang dapat memiliki konsekuensi penting.
Dalam pemrograman fungsional, Anda memiliki banyak kotak fungsi, dan memutuskan bahwa setiap fungsi memiliki satu entri (parameter) dan satu jalan keluar (kembali), dengan ketat tidak ada akses lain ke konteks luar.
Karena tidak ada keadaan dan tidak ada efek samping (sesuai desain), Anda dapat dengan aman menganalisis fungsi apa pun secara terpisah dari keseluruhan dan mengetahui 100% bagaimana ia akan berperilaku dalam keadaan apa pun.
Karena Anda meninju kode dengan unit logis yang mewakili tindakan, juga menjadi mungkin untuk hanya memiliki satu kotak per tindakan biasa.
Ini akan mengecilkan kode proyek skala besar apa pun dengan faktor yang sangat besar dibandingkan dengan OOP yang mempromosikan menyembunyikan banyak fungsi analog di seluruh basis kode di kelas yang berbeda.
Ini juga akan mengalahkan PP sejauh ini karena Anda dapat menumbuhkan proyek lebih lama karena tidak ada lagi status XXXXXXXL untuk dilacak.
Singkatnya, PP mungkin merupakan cara paling sederhana untuk mendekati program sederhana dan FP mungkin adalah cara paling sederhana untuk mendekati program yang kompleks.
Jika Anda faktor dalam tujuan menyatukan semua basis kode dan meningkatkan penggunaan kembali kode, FP harus selalu digunakan, karena itu satu-satunya paradigma yang masuk akal pada skala yang sangat besar, serta satu-satunya paradigma yang memiliki usabilitas 100% (Anda dapat cukup salin tempel fungsi dan gunakan di tempat lain, tanpa overhead apa pun).
Dan Anda mendapatkan pengujian unit yang andal 100% secara gratis.
Dan Anda tidak perlu menulis "final statis pribadi of_doom genius awesome string_1".
Dan Anda mendapatkan paralelisme secara gratis.
sumber
Perbedaan satu kalimat yang sederhana adalah bahwa C ++ adalah C dengan Kelas. (Walaupun jauh lebih banyak sekarang) Saya tidak mengapa Anda tidak ingin mempelajari perbedaan antara keduanya dengan membaca artikel yang bagus tentang C ++ di Wikipedia .... Artikel ini akan banyak membantu Anda: - C ++ (Wikipedia)
Googling juga tentang masalah ini akan membantu. Meminta orang secara acak untuk menjelaskan ini mungkin sulit. IMHO, orang mengerti lebih baik dengan membaca daripada bertanya pada seseorang
sumber