Програмування С, С++теорія та практика (частина 2)
2.7.3 Розміщення УРТК та таблиці УМТ у пам'яті
Розглянемо більш детально, яким саме чином під час виконання програми відбувається пошук підходящої віртуальної функції, що був описаний у попередньому розділі. Для цього використаємо деяку спрощену ієрархію класів, яка містить одну віртуальну функцію:
#іпс1ийе<з'Ьйіо. Ь> с1азз А { іп£ а ; риЬ1іс:
VОІЙ. £ ()
{
ри'Ьз ("Егот А: :£ () ") ;
^г'Ьиаі Vоій. д()
{
ри'Ьз ("Егот А: :д() ") ;
}
};
сіазз В: риЬііс А {
іп£ Ь; риЬііс:
VОІЙ. £ ()
{
ри'Ьз (" Егот В::£ ()");
}
^:сЬиаі VОій. д()
{
ри'Ьз ("Егот В: :д() ") ;
}
};
VОій. Бо_8оте'ЬЬіпд (А& а)
{
а.£() ;
а.д() ;
}
Vоій. таіп ()
{
А а;
В Ь;
Бо_8оте'ЬЬіпд (а) ;
Бо_8оте'ЬЬіпд (Ь);
}
Перш за все відмітимо, що ієрархія класів використовує одночасно віртуальні та звичайні функції. Результат роботи такої програми виглядає так:
|
Егот |
А: |
:£() |
|
Егот |
А: |
:д() |
|
Егот |
А: |
:£() |
|
Егот |
В: |
:д() |
Як видно, звертання до функції Во_8отеіИіпд(А&) з об'єктом класу В приведе до виклику функцій А::/() та В::д(). Це відбувається тому, що у виклику функції Бо_8отеІкіпд (Ь) аргумент посилання В& неявно перетворюється на А&. Адже видно, що А::/() - за визначенням невіртуальна функція, тому було згенеровано код прямого звертання до функції базового класу. Інша справа, коли викликається а.д() в Бо_8отеіИіпд(А&): це призводить до генерації коду, який включає
механізм обробки віртуальних функцій. Схематично виділення пам'яті під розміщення об'єктів може бути зображено таким чином (рис 2.4):
Об'єкт а :
|
Змінна |
Зміщення |
|
||
|
а |
0 |
|||
|
урїг |
2 ^ |
|
А::УМТ |
|
|
|
|
& А::д() |
|
Об'єкт Ь :
|
Змінна |
Зміщення |
|
||
|
а |
0 |
|||
|
урїг |
2 ^ |
|
В::УМТ |
|
|
ь |
4 |
& В::д() |
||
|
|
|
|
|
Рис. 2.4. Схема розміщення об'єктів у пам'яті
Під час виконання код використовує таблицю віртуальних правил УМТ. За покажчиком урґг відбувається визначення, яку саме функцію слід викликати при звертанні до д(). Слід відмітити, що поле урґг класу В має одне і той самий зсув, що і урґг у класі А, отже, Бо_8отеіИіпд(А&) отримує доступ до правильної функції, незалежно від того, який саме передається в Бо_8отеіИіпд(А&). Єдина та ключова відмінність полягає якраз у тому, що урґг для об'єктів класу А та урґг для об'єктів класу В вказують на власні, а отже, різні таблиці віртуальних правил УМТ. Таким чином і реалізується механізм пізнього зв'язування.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
