ファイル名は C++ では無関係です。リンカーはすべてのピースをまとめます。少しの C++ コードをコンパイルするときに知っておく必要があるのは、名前の意味だけです。そして、それが宣言とクラス定義の目的です。これらは名前を導入し、コンパイラにコードを生成するのに十分な情報を提供します:
file1.cpp:
int f(int, bool); // declaration
class Foo; // class declaration
class Bar { int g(); }; // class definition (implies declaration)
int main()
{
Foo * p; // OK, Foo * is a complete type, since we know that
// "Foo" denotes a class
// p->h(); // Error: We don't know what Foo actually is!
Bar b; // OK, we know how size and alignment for Bar
int m = b.g(); // OK, we know what sort of function B::g() is
int n = f(50, true); // OK, we don't need to know what f does
return m + n;
}
上記のコードをコンパイルすると、 との未解決のシンボルが含まf
れますB::g
。1 つ(そして 1 つだけ) の他の翻訳単位にこれらのシンボルの定義が含まれている限り、リンカーはそれらを解決でき、プログラムを正常にリンクできます。
file2.cpp:
int f(int n, bool b) { return b ? n * 2 : 50 - n; }
// include class definition here
int Bar::g() { return f(sizeof(Bar), sizeof(int) == sizeof(char)); }
基本的なルールは、関数またはクラスを宣言したり、クラス a を定義したりできますが、関数とクラス メンバー関数は 1 回しか定義できないということです。例外が 1 つあります。クラス メンバー関数の関数を として宣言した場合、すべての定義が同一であればinline
、実際に繰り返し定義できます。
この規則の当然の帰結は、1 つの翻訳単位で実際の定義を 1 回だけ提供する限り、すべての関数宣言とクラス定義をヘッダー ファイルに安全に配置し、繰り返しインクルードできることです。(そして、inline
ルールにより、クラス定義内に実際のメンバー関数定義を含めることができます。宣言と共に定義されるメンバー関数は暗黙的にinline
.)