クラス・メンバー・リスト内ですでに宣言してあるが、定義はしていないメンバー関数と静的メンバーは、
それらのクラス宣言の外側で定義することができます。
非静的データ・メンバーは、それらのクラスのオブジェクトが作成されたときに定義されます。
静的データ・メンバーの宣言は、定義ではありません。
メンバー関数の宣言は、関数の本体も指定されている場合には、定義になります。
クラス・メンバーの定義がクラス宣言の外側にある場合、メンバー名は、:: (スコープ・レゾリューション) 演算子を使用して、 クラス名によって修飾する必要があります。
以下の例では、クラス宣言の外側でメンバー関数を定義しています。
#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 の検索は、以下の順序に従います。
収容クラスが検索されるときは、収容クラスの定義とそれらの基底クラスだけが検索されるということに留意してください。 基底クラスの定義を含むスコープ (この例ではグローバル・スコープ) は、検索しません。
関連参照