namespace std
{
extern istream cin;
...
}
通过使用extern
,我们声明cin
在其他单元中定义的作为答案
但是如果istream
在中定义/未定义std
,应该会有一些区别,对吧?
编译器有什么区别?
编译器不在乎。如果未定义,链接器将无法将外部对象“链接”到真实对象。
编译器通常会给出一个错误,发现您正在使用 cin 而至少没有声明它。
使用 extern,您可以告诉编译器“简单,简单,相信我,在其他地方有一个 istream 类 cin 的声明和定义。
然后链接器开始行动,调用 cin 的用法和对象本身之间的链接特别“待定”。链接器必须将所有这些调用与它们的目的地结合起来,现在是 cin 存在与否(是否已编译)这一事实的重要性。如果不是,则链接器失败。链接器提供的错误比编译器提供的错误要神秘得多,但探索它们很有趣,因为这是一种非常好的学习方式。
比如下面这段代码没有#include cstdio not stdio.h,但是我们知道printf会在那里,因为标准库总是和我们的程序链接在一起的。是的,它有效。
extern int printf(const char *, ...);
int main()
{
printf( "Hello, world!\n" );
}
编译器必须知道这istream
是一种类型,并且使用extern
关键字告诉它std::cin
存在并且属于该类型。如果istream
在编译器看到该行时尚未将其声明为类型,它将抱怨告诉您它不是类型。
//extern type var; // error 'type' unknown at this point
class type;
extern type var; // ok:'type' is a class even if not fully declared