Як організовуються «пам'ятки» та «класи» OOP в пам'яті з точки зору мови складання?


13

Як організовуються об'єкти в пам'яті?

Наприклад, я знаю, що функція - це фрагмент коду в пам'яті, який очікує параметрів через стек та / або регістри та обробляє власний кадр стека.

Але об’єкти - це набагато складніша структура. Як вони організовані? Чи кожен об'єкт має "посилання" на методи та передає адресу до цього методу?

Було б чудово побачити гарне пояснення цієї теми.

UPD. Я зробив питання більш точним, і мене в основному цікавить статичне введення мов.


4
Він може різко відрізнятися між різними мовами, особливо між динамічно набраними та статично типовими мовами. Чи можете ви звузити своє питання до мов ОО, які вас найбільше цікавлять?
Барт ван Інген Шенау

Я оновив питання, тому вважаю, що динамічно набрані мови важче зрозуміти.
Микола Голуб

Відповіді:


17

Якщо немає динамічної диспетчеризації (поліморфізм), "методи" - це лише цукристі функції, можливо з неявним додатковим параметром. Відповідно, екземпляри класів без поліморфної поведінки по суті є C structs з метою генерування коду.

Для класичної динамічної диспетчеризації в системі статичного типу в основному існує одна переважаюча стратегія: vtables. Кожен екземпляр отримує один додатковий покажчик, який посилається на (обмежене представлення) його типу, головне на vtable: Масив функціональних покажчиків, по одному на метод. Оскільки повний набір методів для кожного типу (у ланцюжку успадкування) відомий під час компіляції, можна призначити послідовні індекси (0..N для N методів) методам і викликати методи, шукаючи вказівник функції в vtable з використанням цього індексу (знову передаючи посилання на екземпляр як додатковий параметр).

Для більш динамічних мов на основі класів зазвичай самі класи є об'єктами першого класу, і кожен об'єкт замість цього має посилання на свій клас класу. Об'єкт класу, у свою чергу, володіє методами в залежності від мови (у Ruby методи є основною частиною об'єктної моделі, в Python вони просто функціонують об'єктами з крихітними обгортками навколо них). Класи, як правило, також зберігають посилання на свої суперкласи, і делегують пошук спадкових методів тим класам, щоб допомогти метапрограмуванню, яке додає та змінює методи.

Є багато інших систем, які не базуються на класах, але вони суттєво відрізняються, тому я виберу лише одну цікаву альтернативу дизайну: Коли ви можете додавати нові (набори) методів для всіх типів за бажанням у будь-якій точці програми ( наприклад, класи типів в Haskell і риси в Rust), повний набір методів не відомий під час компіляції. Щоб вирішити цю проблему, створюється vtable на кожну ознаку та передає їх навколо, коли потрібна реалізація ознаки. Тобто, такий код:

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

складається до цього:

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);

Це також означає, що vtable інформація не вбудована в об’єкт. Якщо ви хочете посилатися на "екземпляр ознаки", який буде вести себе правильно, коли, наприклад, зберігається в структурах даних, що містять багато різних типів, можна створити жирний покажчик (instance_pointer, trait_vtable) . Це фактично узагальнення вищезгаданої стратегії.


5

Це відповідь у значенні прислів’я "якщо ти даєш людині рибу, ти годуєш його протягом дня, а якщо ти навчиш її ловити рибу, ти годуєш його все життя", оскільки твоє питання дуже широке

1. дослідження відкритих інформаційних джерел

Google для "об'єктно-орієнтованого програмування" перелічує досить багато різних відповідних ресурсів.

наприклад, Об'єктно-орієнтоване програмування в Асамблеї, Етан Дж. Елдрідж, 15 грудня 2011 року став третьою ланкою і виглядає добре

2. вчитися з існуючого рукописного коду

Ви можете побачити, як це працює, вивчаючи вихідні коди, написані на деяких популярних мовах асемблерів з явно заявленим OOP, наприклад

3. вчитися з моделей коду, створених компіляторами

Ви можете побачити, як це працює, вивчаючи файли мови проміжної збірки, створені компіляторами OOP на ваш вибір. І компілятори C ++, і FreePascal можуть бути налаштовані так, що ви можете бачити, як виглядає транскрипція коду OOP високого рівня в код мови збірки

4. розгадуйте загадку своїм здоровим глуздом

Зараз уже досить пізно, оскільки ви вже знаєте підказки з інших відповідей. Але раніше в Інтернеті було так просто шукати, і до того, як з’явились сайти, на яких можна отримати відповідь без жодних зусиль протягом декількох годин безкоштовно від добровольця, який засвоїв це важким способом, єдиним доступним для всіх способом роботи був

Запитайте себе: "як би я це здійснив?"

Дуже часто через декілька днів, коли у вашому розумі пробігає процес фонового мислення та після викидання декількох дизайнів паперових проектів, ви виявите, що рішення, яке ви придумали, дуже схоже на рішення, яке придумали та вже реалізували інші програмісти.


Тепер на моїй відповіді є думка, не відповідає безпосередньо на запитання ОП, і старші користувачі з високим рівнем відповідальності можуть вільно відповідати мені

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.