Подтвердить что ты не робот

Чистые виртуальные функции в С++ 11

В С++ 98 нулевой указатель был представлен литералом 0 (или фактически любым постоянным выражением, значение которого равно нулю). В С++ 11 вместо этого мы предпочитаем nullptr. Но это не работает для чистых виртуальных функций:

struct X
{
    virtual void foo() = nullptr;
};

Почему это не работает? Разве это не будет иметь общего смысла? Это просто недосмотр? Будет ли это исправлено?

4b9b3361

Ответ 1

Потому что синтаксис говорит 0, а не выражение или другое нетерминальное соответствие nullptr.

За все время работало только 0. Даже 0L будет плохо сформирован, потому что он не соответствует синтаксису.

Edit

Clang позволяет = 0x0, = 0b0 и = 00 (31.12.2013). Это неверно и должно быть исправлено в компиляторе, конечно.

Ответ 2

Обозначение = 0 для функций virtual не буквально "присваивало null", а скорее специальную нотацию, которая на самом деле обманчива: можно также реализовать чистую виртуальную функцию.

С различными ключевыми словами контекста было бы целесообразнее разрешить abstract, а не = nullptr, а abstract - ключевое слово контекста.

Ответ 3

Именно так определяется грамматика, если мы посмотрим на черновик проекта С++ 9.2 Члены класса, соответствующая грамматика выглядит следующим образом:

[...]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
  = 0
  ^^^

В грамматике конкретно указывается, что спецификатор pure-specifier = 0, а не целостный литерал или выражение, которое, похоже, не оставляет комнаты для маневра. Если я попытаюсь сделать такие вещи, как:

virtual void foo() = 0L;

или

virtual void foo() = NULL ;

gcc говорит мне:

ошибка: недопустимый чистый спецификатор (разрешено только '= 0') до ';' Маркер

и clang говорит:

Ошибка: функция initializer on не похожа на чисто спецификатор

Хотя в обоих случаях работает следующее:

#define bar 0
//...
virtual void foo() = bar;

Также кажется, что clang допускает восьмеричный литерал, шестнадцатеричный литерал и двоичный литерал нуль, который является неправильным поведением.

Обновить

По-видимому Visual Studio принимает NULL и любой нулевой целочисленный литерал, включающий 0L, 0x0, 00 и т.д.... Хотя он не принимает nullptr.

Ответ 4

= 0 имеет там фиксированное значение. На самом деле это не целая ноль. Поэтому вы не можете просто заменить его таким образом.

Ответ 5

Вся точка nullptr (или большая часть точки в любом случае) заключается в том, что она может быть назначена (или используется для инициализации) указателями.

В этом случае вы не инициализируете или не назначаете указатель, поэтому даже не имеет смысла, что вы сможете использовать его в этой ситуации.

Ответ 6

Синтаксис = 0 не использовался для инициализации указателя, он просто указывал синтаксически, что предоставленный virtual был чистым.

Следовательно, синтаксис = 0 для объявления pure virtual не изменяется.

Ответ 7

Это не значит, что это указатель или он должен быть равен nullptr.

= 0 является достаточным и означает, что виртуальная функция должна быть чистой.

Ответ 8

В грамматике С++ 11 допускается только 0 (и это не означает указатель). Поскольку nullptr не 0, он терпит неудачу. NULL работает только тогда, когда NULL определяется как 0 (иногда это случай, но не всегда). Просто используйте 0 здесь или используйте следующий define (если вы действительно хотите использовать null, если это не указатель).

#define VIRTUAL_NULL 0
struct X
{
    virtual void foo() = VIRTUAL_NULL;
};