Компилятор обычно выдает ошибку, обнаружив, что вы используете cin, по крайней мере, не объявляя об этом.
С помощью extern вы можете сказать компилятору "легко, просто, поверьте мне, есть где-то еще объявление и определение для cin класса istream.
Затем компоновщик переходит в действие, и связь между вызовом к использованию cin и самим объектом специально «ожидает». Линкер должен объединить все эти вызовы с их адресатом, и теперь наступает момент, когда факт наличия или отсутствия cin (был скомпилирован или нет) имеет значение. Если нет, то компоновщик не работает. Ошибки, предоставленные компоновщиком, гораздо более загадочны, чем ошибки компилятора, но их интересно исследовать, потому что это очень хороший способ изучения.
Например, следующий фрагмент кода не # включает cstdio, а не stdio.h, но мы знаем, что там будет printf, потому что стандартная библиотека всегда связана с нашей программой. Да, это работает.
extern int printf(const char *, ...);
int main()
{
printf( "Hello, world!\n" );
}