Почему компилятор C++ допускает использование ключевого слова extern в сочетании с определением?
Я случайно сделал ошибку, используя extern
ключевое слово, а затем обнаружил, что компилятор разрешил мою строку кода. Почему разрешена следующая программа? Удаляет ли компилятор ключевое слово extern? Это даже не дает предупреждение.
#include <iostream>
extern void test() { std::cout << "Hello world!" << std::endl; };
int main()
{
test();
}
1 ответ
Это не является необычным, на самом деле, C++ внутренне делает то же самое, обратите внимание на то, что говорит 1.4/6:
Шаблоны, классы, функции и объекты в библиотеке имеют внешнюю связь
Шаблоны в библиотеке, очевидно, тоже имеют определения. И почему бы не они!
Посмотрите, что 3.1/2 и 3.4/2 (выделение добавлено) должны сказать:
Объявление является определением, если оно не объявляет функцию без указания тела функции (8.4), [или] оно не содержит спецификатор extern (7.1.1) или спецификацию связи25 (7.5) и не является ни инициализатором, ни функциональным телом
[...]
Когда имя имеет внешнюю связь, обозначаемая им сущность может именоваться именами из областей действия других единиц перевода или из других областей той же единицы перевода.
Ваше объявление имеет тело функции, так что это определение, и это явно, вполне допустимо. Функция имеет внешнюю связь, что означает, что вы можете ссылаться на нее по имени из области видимости в другом модуле перевода, но вы не обязаны это делать.
Вы все еще можете называть его по имени в текущем модуле перевода, и это то, что вы делаете.
Обратите внимание, что есть пункт об именах в области имен, так что вы используете extern
Ключевое слово в любом случае несколько избыточно.