Vtable разполагане на напълно чист виртуален клас

Според моите (ограничени) познания за спецификацията на C++, vtable на клас с виртуални членове се поставя в дефиницията на първия не-чист не-вграден виртуален метод. Как компилаторите обработват класове, които наследяват от клас с ВСИЧКИ чисти виртуални методи (интерфейси, например)? Къде е поставена vtable в този случай?


person tgoodhart    schedule 06.01.2011    source източник
comment
Самата спецификация на C++ не казва нищо за vtables.   -  person John Dibling    schedule 06.01.2011
comment
Тежък детайл от изпълнението. MSVC++ има __declspec(novtable) за потискане на такава vtable. И нестандартната ключова дума __interface да направи същото.   -  person Hans Passant    schedule 06.01.2011


Отговори (3)


Vtable съхранява адресите на внедрените виртуални методи. Ако всички методи на даден клас са чисто виртуални и нито един не е имплементиран, тогава не е необходимо да се генерира vtable.

Не бихте могли да използвате такъв клас дълго време без някои класове, които произлизат от него и прилагат методите. Всеки клас с внедрени виртуални методи има своя собствена единствена vtable, съдържаща адреси за всички виртуални методи: тя по никакъв начин не препраща към vtables на базовите класове; адресите се дублират. Така че, ако имате клас, който наследява от друг клас, този клас ще използва само своя собствена vtable. Не се интересува от vtable на базовия клас; тази vtable дори не е необходимо да съществува.

Самата спецификация на C++ не казва нищо за vtables; те са просто поведение на компилатор, което е станало обичайно.

РЕДАКТИРАНЕ от 2020 г.: Написах това преди почти десетилетие. Подозирам, че го написах по памет и личен опит. Два коментара по-долу показват, че компилаторите правят правят vtables за базови класове (за хвърляне на грешки), въпреки че ако е така, не знам как бихте конструирали обект за тях и че някои компилатори използват повторно vtables на базови класове. Изглежда, че никой не е добавил нищо от 2011 г., а сега имам когнитивен спад и вече е трудно наистина да мисля много, така че направете собствено проучване, ако някои подробности тук са от решаващо значение.

person fuzzyTew    schedule 06.01.2011
comment
интересно Бих си помислил, че наличието на дублиращи се таблици би нарушило някакво правило за една дефиниция. - person tgoodhart; 06.01.2011
comment
Нито една от таблиците не се дублира. Нова таблица се генерира само ако виртуален метод е имплементиран от този клас; това прави уникална vtable, съдържаща указател към тази реализация. Таблицата ще съдържа дублирани адреси за всички непроменени виртуални методи. - person fuzzyTew; 06.01.2011
comment
‹quote›Ако всички методи на един клас са чисто виртуални, нито един не е имплементиран‹/quote› Това просто не е вярно. В C++ чисто виртуално не означава липса на реализация. - person Ben Voigt; 06.01.2011
comment
Бен, прав си. Редактирах отговора си и гласувах за вашия. - person fuzzyTew; 06.01.2011
comment
Всъщност компилаторът ще генерира записи за чисти виртуални функции с грешки, дори когато те нямат дефинирана от потребителя реализация. Това се прави, за да се уловят и докладват грешки, когато се извика чиста виртуална функция. - person Gene Bushuyev; 06.01.2011
comment
‹quote›Всеки клас с внедрени виртуални методи има своя собствена единствена vtable, съдържаща адреси за всички виртуални методи: тя по никакъв начин не препраща към vtables на базовите класове‹/quote› -- Това не е задължително вярно. Някои стари компилатори на Borland прилагат точно указател към базова vmt схема, за да пестят памет. Изглежда вече никой не се интересува от това. - person Gene Bushuyev; 06.01.2011
comment
GCC има ли поведението, което описвате? Къде поставя своята vtable за чисти виртуални базови класове? Би било чудесно да има правилен отговор на въпроса. - person fuzzyTew; 06.01.2011

Стандартът C++ не уточнява нищо относно разположението на vtable или дори съществуването на v-table. Той просто указва поведението и v-таблицата се оказва най-простата реализация, следователно широко използвана.

Практически казано, единствената причина v-таблицата да съществува за абстрактен клас е за използване по време на изграждане и разрушаване, когато динамичният тип на обекта е абстрактният клас.

В клас само с чисти виртуални функции очевидно не може да има конструктори (тъй като конструкторите не могат да бъдат виртуални). Въпреки това деструкторите със сигурност МОГАТ да бъдат виртуални.

Вашият клас все още може да има чист виртуален деструктор с имплементация и след това се изисква v-таблица (или еквивалентни подробности за реализация).

Но имплементациите на чисто виртуални функции са рядкост и не биха били направени при дефиниране на интерфейс.

person Ben Voigt    schedule 06.01.2011

Не се нуждаете от vtable, докато нямате екземпляр.

person JB.    schedule 06.01.2011
comment
Какъв пример? Компилаторът няма представа, когато компилира един TU, дали чистите виртуални функции ще имат имплементация, дефинирана в друг TU. Изпълнителят на компилатор може да реши как да се справи с него и може да бъде разумно решение да се създаде vtable и да се зададат указатели към функцията за грешка, за да се докладват незаконни извиквания към недефинирани чисти виртуални функции. - person Gene Bushuyev; 06.01.2011
comment
Измина известно време, откакто написах това (уведомен чрез редакция), но предполагам, че мисълта ми беше: или е абстрактно (има чисти виртуални методи), следователно не може да бъде инстанцирано и не се нуждае от vtable, или не е, следователно има отменени всички наследени чисти виртуални методи. Случаят на OP е чисто абстрактен. Компилаторът е трябва да знае, когато компилира всеки TU, дали методите са чисти или не, както се съдържа в декларацията на класа. - person JB.; 20.09.2019