Bagaimana "objek" dan "kelas" OOP diatur dalam memori dalam hal bahasa rakitan?

13

Bagaimana benda-benda diatur dalam memori?

Sebagai contoh, saya tahu bahwa suatu fungsi adalah sepotong kode dalam memori, yang mengharapkan parameter melalui stack dan / atau register dan menangani frame stack itu sendiri.

Tetapi objek adalah struktur yang jauh lebih rumit. Bagaimana mereka diorganisasikan? Apakah setiap objek memiliki "tautan" ke metode dan meneruskan alamat ke dirinya sendiri ke metode itu?

Sangat menyenangkan melihat penjelasan yang bagus tentang topik ini.

UPD. Saya membuat pertanyaan lebih tepat, dan saya terutama tertarik pada bahasa pengetikan yang statis.

Nikolai Golub
sumber
4
Ini dapat sangat bervariasi antara bahasa yang berbeda, terutama antara bahasa yang diketik secara dinamis dan yang diketik secara statis. Bisakah Anda mempersempit pertanyaan Anda ke bahasa OO yang paling Anda minati?
Bart van Ingen Schenau
Saya telah memperbarui pertanyaan, jadi saya pikir bahasa yang diketik secara dinamis lebih sulit untuk dipahami.
Nikolai Golub

Jawaban:

17

Jika tidak ada pengiriman dinamis (polimorfisme), "metode" hanyalah fungsi yang manis, mungkin dengan parameter tambahan implisit. Dengan demikian, instance kelas tanpa perilaku polimorfik pada dasarnya adalah C structuntuk keperluan pembuatan kode.

Untuk pengiriman dinamis klasik dalam sistem tipe statis, pada dasarnya ada satu strategi utama: vtables. Setiap instance mendapatkan satu pointer tambahan yang mengacu pada (representasi terbatas) tipenya, yang terpenting adalah vtable: Array pointer fungsi, satu per metode. Karena set lengkap metode untuk setiap jenis (dalam rantai pewarisan) diketahui pada waktu kompilasi, seseorang dapat menetapkan indeks berurutan (0..N untuk metode N) ke metode dan memanggil metode dengan mencari penunjuk fungsi di vtable menggunakan indeks ini (lagi melewati referensi instance sebagai parameter tambahan).

Untuk bahasa berbasis kelas yang lebih dinamis, biasanya kelas itu sendiri adalah objek kelas satu dan setiap objek sebaliknya memiliki referensi ke objek kelasnya. Objek kelas, pada gilirannya, memiliki metode dalam beberapa cara bergantung pada bahasa (di Ruby, metode adalah bagian inti dari model objek, dengan Python mereka hanya berfungsi sebagai objek dengan pembungkus kecil di sekitar mereka). Kelas-kelas biasanya menyimpan referensi ke superclass (es) mereka juga, dan mendelegasikan pencarian metode yang diwariskan ke kelas-kelas untuk membantu metaprogramming yang menambah dan mengubah metode.

Ada banyak sistem lain yang tidak didasarkan pada kelas, tetapi mereka berbeda secara signifikan, jadi saya hanya akan memilih satu alternatif desain yang menarik: Ketika Anda dapat menambahkan metode baru (set) ke semua jenis di mana saja di mana saja dalam program ini ( mis. ketik kelas di Haskell dan ciri-ciri di Rust), set lengkap metode tidak diketahui saat kompilasi. Untuk mengatasinya, kita membuat vtable per trait dan meneruskannya ketika implementasi trait diperlukan. Yaitu, kode seperti ini:

void needs_a_trait(SomeTrait &x) { x.method2(1); }
ConcreteType x = ...;
needs_a_trait(x);

dikompilasi menjadi ini:

functionpointer SomeTrait_ConcreteType_vtable[] = { &method1, &method2, ... };
void needs_a_trait(void *x, functionpointer vtable[]) { vtable[1](x, 1); }
ConcreteType x = ...;
needs_a_trait(x, SomeTrait_ConcreteType_vtable);

Ini juga berarti informasi vtable tidak tertanam di objek. Jika Anda ingin referensi ke "instance of a trait" yang akan berperilaku benar ketika, misalnya, disimpan dalam struktur data yang berisi banyak jenis berbeda, orang dapat membuat penunjuk gemuk (instance_pointer, trait_vtable) . Ini sebenarnya merupakan generalisasi dari strategi di atas.


sumber
5

Ini adalah jawaban dalam pengertian pepatah "jika Anda memberi ikan kepada seseorang, Anda memberinya makan sehari, sedangkan jika Anda mengajarinya memancing, Anda memberinya makan seumur hidup" karena pertanyaan Anda sangat luas

1. penelitian sumber informasi terbuka

Google untuk "pemrograman berorientasi objek perakitan" mencantumkan cukup banyak sumber daya relevan yang berbeda.

misalnya Pemrograman Berorientasi Objek dalam Majelis, Ethan J. Eldridge, 15 Desember 2011 datang sebagai tautan ke-3 dan terlihat bagus

2. belajar dari kode tulisan tangan yang ada

Anda dapat melihat cara kerjanya dengan mempelajari kode sumber yang ditulis dengan beberapa bahasa rakitan populer dengan OOP yang dinyatakan secara eksplisit misalnya

3. belajar dari pola kode yang dihasilkan oleh kompiler

Anda dapat melihat cara kerjanya dengan mempelajari file bahasa rakitan perantara yang diproduksi oleh kompiler OOP pilihan Anda. Kompiler C ++ dan FreePascal dapat dikonfigurasi sehingga Anda dapat melihat seperti apa transkripsi kode OOP tingkat tinggi ke dalam kode bahasa assembly

4. pecahkan puzzle dengan akal sehat Anda

Sekarang sudah terlambat karena Anda sudah tahu petunjuk dari jawaban lain. Tetapi sebelum internet sangat mudah untuk dicari dan sebelum ada situs-situs di mana Anda bisa mendapatkan jawaban Anda tanpa kesulitan dalam beberapa jam gratis dari beberapa sukarelawan yang mempelajarinya dengan cara yang sulit, satu-satunya metode kerja yang tersedia secara gratis untuk siapa pun adalah

Tanyakan kepada diri sendiri: "bagaimana saya menerapkannya?"

Sangat sering setelah beberapa hari proses pemikiran latar belakang berjalan dalam pikiran Anda dan setelah membuang beberapa desain kertas draft Anda akan menemukan bahwa solusi yang Anda buat sangat mirip dengan solusi yang dibuat oleh programmer lain dan sudah diterapkan


Sekarang adalah jawaban berdasarkan pendapat saya, tidak secara langsung menjawab pertanyaan OP dan pengguna senior yang bereputasi tinggi dapat dengan bebas menurunkan saya

xmojmr
sumber