Чому чиста віртуальна функція ініціалізується на 0?


147

Ми завжди оголошуємо чисту віртуальну функцію такою:

virtual void fun () = 0 ;

Тобто, це завжди присвоюється 0.

Я розумію, що це ініціалізація запису vtable для цієї функції до NULL, а будь-яке інше значення тут призводить до помилки часу компіляції. Це правильне розуміння чи ні?


12
Зауважте, що vtable - це не вимога мови, а лише варіант реалізації для віртуальних методів. Компілятор міг би створити ту саму абстракцію з іншою реалізацією (тобто без vtable та без будь-якого елемента, який буде 0)
David Rodríguez - dribeas

@hype Повторне ваше додаткове запитання - ось що говорить моя відповідь (та кілька інших).

Просто цікаво, що станеться, якщо я дам, virtual void func() = 100;
krithikaGopalakrisnan

Відповіді:


161

Причина =0використовується в тому, що Bjarne Stroustrup не думав, що він може отримати інше ключове слово, наприклад, "чисте" минуле спільноти C ++ під час впровадження функції. Це описано у його книзі «Дизайн та еволюція C ++» , розділ 13.2.3:

Був обраний синтаксис цікавого = 0 ... тому що я не бачив жодного шансу отримати нове ключове слово.

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


4
Так, це просто синтаксис. Я бачив безліч проектів, які #define PURE = 0, і вони скажуть віртуальну пустоту Foo () ЧИСТО;
i_am_jorf

79
Будь ласка, тримайте мене від цих проектів :-)

27
Це набагато гірше, ніж #define ПОЧАТИ {#define END} ;-), і я це бачив іноді.
Toon Krijthe

5
Цей витончений предмет змушує мене думати, що C ++ не дуже відполірований. Дивно, враховуючи, що його так багато використовують. Я сподіваюся, що мова буде кращою з плином днів.
jokoon

19
Так, іншими словами, Bjarne "зіткнувся з терміном" і "використав рубець", щоб подолати "недолік дизайну";) (Тільки бути вибагливим)
Карл

78

Як і у більшості запитань "Чому" щодо дизайну C ++, перше місце, на яке слід звернути увагу, - це "Дизайн та еволюція C ++" , автор Bjarne Stroustrup 1 :

Цікавий =0синтаксис був обраний через очевидну альтернативу введення нового ключового слова pureабо abstractтому, що я не бачив жодного шансу прийняти нове ключове слово. Якби я запропонував pure, випуск 2.0 був би поставлений без абстрактних класів. З урахуванням вибору між приємнішим синтаксисом та абстрактними класами, я вибрав абстрактні класи. Замість того, щоб ризикувати затримкою і проводити певні бої pure , я використав традицію C і C ++, щоб використовувати "0", щоб представити "не там". У =0синтаксичних припадках з моєї точкою зору , що тіло функції є ініціалізатор для функції також з (спрощено, але , як правило , адекватними) через велику кількість віртуальних функцій реалізуються як вектор покажчиків на функцію. [...]

1 §13.2.3 Синтаксис


29

У розділі 9.2 стандарту C ++ наведено синтаксис для членів класу. Він включає це виробництво:

pure-specifier:
    = 0

У цінності немає нічого особливого. "= 0" - це лише синтаксис висловлювання "ця функція є чисто віртуальною". Це не має нічого спільного з ініціалізацією або нульовими покажчиками або числовим значенням нуль, хоча подібність до цих речей може мати мнемонічне значення.


5
+1 для посилання на стандарт C ++. Це дивно, що одна з найкращих можливих відповідей і отримала поки що лише 1 голос. Читання стандарту має бути першим кроком для вирішення питань на C ++.
mloskot

7
@mloskot: можливо, тому, що він не відповідає на питання ОП, просто перетворює ситуацію?
просто хтось

6
@just когось - Він включає стандартне цитування, в якому зазначено, що таке синтаксис чистого декларації віртуальної функції, і що синтаксис використовує pure-specifier = 0Що ще ви хотіли б знати? Це було б те саме, що запитувати, чому функціональне тіло обернуто {} Відповідь буде, тому що це визначає синтаксис C ++.
mloskot

19

Я не впевнений, чи є за цим сенс. Це просто синтаксис мови.


16

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

= 0Синтаксис , можливо , дійсно був обраний , так як вона нагадує установку записи в таблиці віртуальної 0, але це чисто символічний характер . (Більшість компіляторів присвоюють такі записи vtable заглушці, яка видаляє помилку перед тим, як перервати програму.) Синтаксис був обраний головним чином, тому що він раніше нічого не використовувався, і це врятувало введення нового ключового слова.


3
+1 для пояснення недоліків введення нового ключового слова. Це корисно для розуміння обґрунтування, але синтаксис C ++ здається мені абсурдно заплутаним, і я б хотів, щоб вони зробили його більш зрозумілим для людини - pureключове слово було б чудовим у моїй книзі. У будь-якому разі, добре зрозуміти обґрунтування.
Кіт Пінсон

@KeithPinson Якщо ви хочете отримати чисте ключове слово, ви можете #define pure = 0.
jdh8

@ jdh8: Фу. Просто ... Тьфу.
sbi

Як зауваження, в класі з Bjarne він сказав, що він дійсно хотів отримати "чисте" ключове слово в C ++ ... але він намагався ввести його дуже пізно в циклі, перш ніж компілятор C ++ буде відправлений (IIRC менше двох тижнів). Нібито, це не вдалося.
ThePhD

@ThePhD: ISTR він також говорить про це десь у D&E. (Я занадто лінивий, щоб подивитися на це.)
sbi

11

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


2
-0: коли у вас немає нічого істотного, щоб сказати самостійно, використовуйте обширну цитату (див. Відповідь Джері Коффіна за +1;)
просто хтось

7

У цьому випадку нічого не "ініціалізовано" або "присвоєно" нулю. = 0лише синтаксична конструкція, що складається з =і0 лексеми, яка не має абсолютно ніякого відношення ні до ініціалізації або присвоювання.

Це не має жодного відношення до жодного фактичного значення у "vtable". Мова C ++ не має поняття "vtable" або щось подібне. Різні "vtables" - це не що інше, як лише деталі конкретних реалізацій.


3

Я пам’ятаю, що читав, що виправданням смішного синтаксису було те, що було легше (з точки зору прийняття стандартів), ніж ввести ще одне ключове слово, яке зробить те саме.

Я вважаю, що це було згадано у програмі Bjarne Stroustrup в «Дизайн та еволюція C ++».


2

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


2

= 0Оголошує чисту віртуальну функцію .

Зрозуміло, що це ініціалізація запису vtable для цієї функції до NULL, а будь-яке інше значення призводить до помилки часу компіляції.

Я не думаю, що це правда. Це просто особливий синтаксис. Vtable визначається реалізацією. Ніхто не каже, що запис vtable для чистого члена повинен бути фактично нульовим при побудові (хоча більшість компіляторів обробляють vtables подібними).


4
Це насправді не так. Немає нічого поганого в наданні визначення чистої віртуальної функції. Єдине, що = 0робиться - це зробити весь клас абстрактним і забороняє віртуальні дзвінки до чистих функцій. Невіртуальні дзвінки все ще досконало в порядку, і тоді використовується визначення (якщо ви його надали).
ANT

Подивіться на вихідні болти. Тут немає місця для неоднозначності чи спекуляцій. Я погляну сам пізніше
Льюїс Келсі

Здається, що він замінює запис на __cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/… замість Base :: f ()
Льюїс Келсі

1

Ну, ви також можете ініціалізувати запис vtable, щоб вказати на фактичну функцію "

 virtual void fun()
 {
     //dostuff()
 }

Начебто інтуїтивно зрозуміло, що запис vtable можна або визначити нікуди (0) або на функцію. Якщо ви зможете вказати своє власне значення, це, ймовірно, призведе до того, що воно вказує на сміття замість функції. Але тому "= 0" дозволено, а "= 1" - ні. Я підозрюю, що Ніл Баттерворт має рацію щодо того, чому "= 0" взагалі використовується


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