История изменений
Исправление mix_mix, (текущая версия) :
тупым копированием со статическим связыванием
Что-то я не распарсил. У нас есть класс A, у него есть vtbl с функциями foo (0x100), bar (0x200) и baz (0x300), в скобках адреса функций в памяти. Вызов a->foo(...)
в компайл-тайме раскрывается в (a->(*vptr)[0])(a, ...)
. Потом у нас есть наследник B, у него есть своя vtbl с функциями foo (0x400), bar (0x200), baz (0x300) и quux (0x500), по адресам поведение уже должно быть понятно — foo замещается, остальные остаются от предка, добавляется новая quux. Вызов b->foo(...)
ничем не отличается: (b->(*vptr))[0](b, ...)
. Ты это имел в виду? Что вся vtbl копируется? Ну так мы гораздо меньше всасываем на производительности, для вызова виртуальной функции нам нужно в худшем случае разыменовать всего три указателя (ссылка на экземпляр класса, vptr и vtbl[n]). Попробуй описать на таком же уровне, как это будет выглядеть в динамике.
Исправление mix_mix, :
тупым копированием со статическим связыванием
Что-то я не распарсил. У нас есть класс A, у него есть vtbl с функциями foo (0x100), bar (0x200) и baz (0x300), в скобках адреса функций в памяти. Вызов a->foo(...)
в компайл-тайме раскрывается в (a->(*vptr)[0])(a, ...)
. Потом у нас есть наследник B, у него есть своя vtbl с функциями foo (0x400), bar (0x200), baz (0x300) и quux (0x500), по адресам поведение уже должно быть понятно. Вызов b->foo(...)
ничем не отличается: (b->(*vptr))[0](b, ...)
. Ты это имел в виду? Что вся vtbl копируется? Ну так мы гораздо меньше всасываем на производительности, для вызова виртуальной функции нам нужно в худшем случае разыменовать всего три указателя (ссылка на экземпляр класса, vptr и vtbl[n]). Попробуй описать на таком же уровне, как это будет выглядеть в динамике.
Исправление mix_mix, :
тупым копированием со статическим связыванием
Что-то я не распарсил. У нас есть класс A, у него есть vtbl с функциями foo (0x100), bar (0x200) и baz (0x300), в скобках адреса функций в памяти. Вызов a->foo(...)
в компайл-тайме раскрывается в (a->(*vptr)[0])(a, ...)
. Потом у нас есть наследник B, у него есть своя vtbl с функциями foo (0x400), bar (0x200), baz (0x300) и quux (0x500), по адресам поведение уже должно быть понятно. Вызов b->foo(...)
ничем не отличается: (b->(*vptr))[0](b, ...)
. Ты это имел в виду? Что вся vtbl копируется? Ну так мы гораздо меньше всасываем на производительности, нам в худшем случае нужно разыменовать три указателя (ссылка на экземпляр класса, vptr и vtbl[n]).
Исходная версия mix_mix, :
тупым копированием со статическим связыванием
Что-то я не распарсил. У нас есть класс A, у него есть vtbl с функциями foo (0x100), bar (0x200) и baz (0x300), в скобках адреса функций в памяти. Вызов a->foo(...)
в компайл-тайме раскрывается в (a->(*vptr)[0])(a, ...)
. Потом у нас есть наследник B, у него есть своя vtbl с функциями foo (0x400), bar (0x200), baz (0x300) и quux (0x500), по адресам поведение уже должно быть понятно. Вызов b->foo(...)
ничем не отличается: (b->(*vptr))[0](b, ...)
.