namespace std
{
extern istream cin;
...
}
を使用して、他のユニットで定義されていることを答えextern
として宣言しますcin
しかし、istream
で定義済み/未定義の場合はstd
、違いがあるはずですよね?
コンパイラの違いは何ですか?
コンパイラは気にしません。外部オブジェクトが未定義の場合、リンカは外部オブジェクトを実際のオブジェクトに「リンク」できません。
コンパイラは通常、少なくとも宣言せずに cin を使用していることを検出してエラーを出します。
extern を使用すると、コンパイラに「簡単、簡単、信頼してください。istream クラスの cin の宣言と定義が別の場所にある」と伝えることができます。
次に、リンカが動作を開始し、cin の使用への呼び出しとオブジェクト自体の間のリンクが特別に「保留中」になります。リンカーは、これらすべての呼び出しを宛先に結合する必要があり、現在、cin が存在するかどうか (コンパイルされているかどうか) が重要になります。そうでない場合、リンカーは失敗します。リンカーによって提供されるエラーは、コンパイラによって提供されるものよりもはるかに不可解ですが、学習するための非常に良い方法であるため、調査するのは興味深いものです。
たとえば、次のコードはstdio.h ではなく cstdio を#includeしていませんが、標準ライブラリが常にプログラムにリンクされているため、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