メンバー・スコープ (C++ のみ)

クラス・メンバー・リスト内で既に宣言してあるが、定義はしていないメンバー関数と静的メンバーは、 それらのクラス宣言の外側で定義することができます。 非静的データ・メンバーは、それらのクラスのオブジェクトが作成されたときに定義されます。 静的データ・メンバーの宣言は、定義ではありません。 メンバー関数の宣言は、関数の本体も指定されている場合には、定義になります。

クラス・メンバーの定義がクラス宣言の外側にある場合、 メンバー名は、:: (スコープ・レゾリューション) 演算子を使用して、 クラス名によって修飾する必要があります。

以下の例では、クラス宣言の外側でメンバー関数を定義しています。

#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 は 戻しません。

クラス・メンバーの名前は、そのクラスに対してローカルなものです。 いずれのクラス・アクセス演算子 (. (ドット)、-> (矢印)、または :: (スコープ・レゾリューション) も使用しない場合、クラス・メンバーを使用できるのは、そのクラスおよびネスト・クラスのメンバー関数内のみです。 ネスト・クラス内で、:: 演算子で修飾されていないものは、 型、列挙、および静的メンバーしか使用できません。

メンバー関数本体で名前を検索する順序は、次のとおりです。

  1. メンバー関数本体自体の中
  2. すべてのエンクロージング・クラスの中 (それらのクラスの継承メンバーを含めて)
  3. 本体宣言の字句範囲の中
継承メンバーを含めた、エンクロージング・クラスの検索の例を、以下に示します。
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 の検索は、以下の順序に従います。

  1. 関数 f の本体の中
  2. X およびその基底クラス C の中
  3. Y およびその基底クラス B の中
  4. Z およびその基底クラス A の中
  5. f の本体の字句範囲の中。この場合はグローバル・スコープ

収容クラスが検索されるときは、 収容クラスの定義とそれらの基底クラスだけが検索されるということに留意してください。 基底クラスの定義を含むスコープ (この例ではグローバル・スコープ) は、検索しません。