クラス・メンバー・リスト内で既に宣言してあるが、定義はしていないメンバー関数と静的メンバーは、 それらのクラス宣言の外側で定義することができます。 非静的データ・メンバーは、それらのクラスのオブジェクトが作成されたときに定義されます。 静的データ・メンバーの宣言は、定義ではありません。 メンバー関数の宣言は、関数の本体も指定されている場合には、定義になります。
クラス・メンバーの定義がクラス宣言の外側にある場合、 メンバー名は、:: (スコープ・レゾリューション) 演算子を使用して、 クラス名によって修飾する必要があります。
以下の例では、クラス宣言の外側でメンバー関数を定義しています。
#include <iostream>
using namespace std;
struct X {
int a, b ;
// member function declaration only
int add();
};
// global variable
int a = 10;
// define member function outside its class declaration
int X::add() { return a + b; }
int main() {
int answer;
X xobject;
xobject.a = 1;
xobject.b = 2;
answer = xobject.add();
cout << xobject.a << " + " << xobject.b << " = " << answer << endl;
}
この例の出力は 1 + 2 = 3 となります。
すべてのメンバー関数は、それらがクラス宣言の外側で定義されている場合 であっても、クラス・スコープ内にあります。上記の例では、メンバー関数 add() は データ・メンバー a を戻しますが、グローバル変数 a は 戻しません。
クラス・メンバーの名前は、そのクラスに対してローカルなものです。 いずれのクラス・アクセス演算子 (. (ドット)、-> (矢印)、または :: (スコープ・レゾリューション) も使用しない場合、クラス・メンバーを使用できるのは、そのクラスおよびネスト・クラスのメンバー関数内のみです。 ネスト・クラス内で、:: 演算子で修飾されていないものは、 型、列挙、および静的メンバーしか使用できません。
メンバー関数本体で名前を検索する順序は、次のとおりです。
class A { /* ... */ };
class B { /* ... */ };
class C { /* ... */ };
class Z : A {
class Y : B {
class X : C { int f(); /* ... */ };
};
};
int Z::Y::X f()
{
char j;
return 0;
}
この例で、関数 f の定義内での名前 j の検索は、以下の順序に従います。
収容クラスが検索されるときは、 収容クラスの定義とそれらの基底クラスだけが検索されるということに留意してください。 基底クラスの定義を含むスコープ (この例ではグローバル・スコープ) は、検索しません。