4

Рассмотрим следующую программу:Почему MSVS позволяет использовать NULL в качестве чистой спецификации виртуальной функции?

struct Test 
{ 
    virtual void foo()=NULL; 
}; 
int main() 
{ } 

г ++ 4.8.1 дает ожидаемую ошибку следующим образом:

[Error] invalid pure specifier (only '= 0' is allowed) before ';' token 

Clang дает следующее сообщение об ошибке:

error: initializer on function does not look like a pure-specifier 

Но когда я попробовал его на МСВС 2010 он компилирует & работает отлично. Я думаю, что g ++ & clang прав в этом случае. Что говорит об этом стандарт? Я отключил расширения компилятора, используя параметр командной строки \ Za, но MSVS по-прежнему принимает этот код. Почему это не дает никаких ошибок?

Я также пробовал это на онлайн компиляторе VC++ here, который был последний раз обновлен 8 июля 2015 года. Неужели это ошибка в MSVS 2010 & 2015?

+1

См. [Чистые виртуальные функции в C++ 11] (http://stackoverflow.com/q/20861346/1708801), это неверно, кажется ошибкой. –

+0

@ShafikYaghmour: Итак, есть ли отчет об ошибке? – Destructor

+6

@PravasiMeet Я бы предположил, что VS2010 только что определил 'NULL'' '0'. –

ответ

2

Согласно MSDN, NULL определяется как нечто, что достаточно близко к 0 для MSVC++ для глотания. Вот и все.

Попробуйте сделать #undef NULL перед этим кодом, и он должен правильно сломать компиляцию.

+1

Я думаю, что ссылка только для C, '(void *) 0' не является допустимым определением для' NULL' в C++. – TartanLlama

+0

@TartanLlama, но с тех пор, когда MSVC++ заботится об этом :) –

+0

@TartanLlama: хорошее наблюдение. – Destructor

2

NULL указан как константа константы нулевой указатель C++, которая является интегральным постоянным выражением, которое оценивается до нуля или значением класса std::nullptr_t. Таким образом, 0, 0L или nullptr являются действительными реализациями NULL.

Ваши версии Clang и GCC, вероятно, определяют его как 0L или nullptr, тогда как версия MSVC определяет его как 0. В этом случае препроцессор заменит NULL на 0, что сделает вашу программу хорошо сформированной.

1

Грамматика в разделе 9.2Члены класса говорит следующее:

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

Так чисто спецификатор должен быть буквальным 0. Скорее всего, NULL определяется как 0 для MSVC, но его не обязательно следует указывать как 0, еще одна возможность - 0L, что не допускается грамматикой, и это возможно, что использование gcc и clang.

Мы можем увидеть это из раздела 18.2:

The macro NULL is an implementation-defined C++ null pointer constant in this International Standard 194

сноска говорит:

Possible definitions include 0 and 0L, but not (void*)0.

и раздел 4.10 говорит:

A null pointer constant is an integer literal (2.14.2) with value zero

, исключающий (void*)0.

Более ранние версии clang и MSVC accepted other integer literals, но похоже, что clang исправил это в последней редакции.

Смежные вопросы