クラスの初期化
コンストラクタ:インデックス への移動
public メンバーのみを持ち、コンストラクタも基底クラスもないクラスのオブジェクトは(典型的なのが構造体)、初期化リストで初期化することができます。クラスにClassがある場合、そのオブジェクトは初期化されるか、デフォルト コンストラクタを持たなければなりません。後者は、明示的に初期化されないオブジェクトに使用されます。
コンストラクタを持つクラスのオブジェクトは、括弧内の式リストで初期化することができます。このリストは、コンストラクタへの引数リストとして使用されます。代わりに、=(等号)の後に単独の値を指定する方法もあります。単独の値は、そのクラスのコンストラクタが受け入れる最初の引数と同一の型になり、この場合は引数はそれ以上ないか、あるいは残りの引数はデフォルトの値を持つことになります。この単独の値は、そのクラス型のオブジェクトであってもかまいません。前者の場合、一致するコンストラクタがオブジェクトを作成するために呼び出されます。後者の場合、コピー コンストラクタがオブジェクトの初期化を行うために呼ばれます。
class X
{
int i;
public:
X(); // function bodies omitted for clarity
X(int x);
X(const X&);
};
void main()
{
X one; // default constructor invoked
X two(1); // constructor X::X(int) is used
X three = 1; // calls X::X(int)
X four = one; // invokes X::X(const X&) for copy
X five(two); // calls X::X(const X&)
}
コンストラクタは、2 通りの方法でそのメンバーに値を代入できます:
1. 値をパラメータとして受け取り、コンストラクタの関数の本体の中でメンバー変数に代入することができます。
class X
{
int a, b;
public:
X(int i, int j) { a = i; b = j }
};
2. 初期化子リストを、関数本体の前に使用することができます。
class X
{
int a, b, &c; // Note the reference variable.
public:
X(int i, int j) : a(i), b(j), c(a) {}
};
初期化子リストは、参照変数の初期化のためにのみ、配置します。
どちらの場合も、X x(1, 2) の初期化は、1 の値を x::a に、2 を x::b に代入します。第2メソッドでは、初期化子リストは、基底クラスのコンストラクタに値を渡すメカニズムを提供します。
メモ: 基底クラスのコンストラクタは、派生クラスから呼び出されるようにするには、public または protected として宣言されていなければなりません。
class base1
{
int x;
public:
base1(int i) { x = i; }
};
class base2
{
int x;
public:
base2(int i) : x(i) {}
};
class top : public base1, public base2
{
int a, b;
public:
top(int i, int j) : base1(i*5), base2(j+i), a(i) { b = j;}
};
このクラス階層では、top one(1, 2) の宣言によって、base1 は値 5 で初期化され、base2 は値 3 で初期化されます。初期化の方法は、混在してもかまいません。
上記の説明の通り、基底クラスは、宣言された順序で初期化されます。その後、メンバーも宣言された順序で初期化されます(初期化リストには依存しない)。
class X
{
int a, b;
public:
X(int i, j) : a(i), b(a+j) {}
};
このクラスでは、X x(1,1) の宣言により、1 は x::a に、2 は x::b に代入されます。
基底クラス コンストラクタは、いずれの派生クラス メンバーの構築よりも先に呼び出されます。派生クラスの値が変更されても、基底クラスの作成に影響はありません。
class base
{
int x;
public:
base(int i) : x(i) {}
};
class derived : base
{
int a;
public:
derived(int i) : a(i*10), base(a) { } // Watch out! Base will be
// passed an uninitialized 'a' };
このクラスの設定では、derived d(1) の呼び出しにより、基底クラス メンバー x の値は 10 になりません。基底クラス コンストラクタに渡される値は、未定義になります。
初期化子リストを、インライン コンストラクタに入れたくない場合、そのリストをクラス定義に入れないでください。代わりに、関数が定義される位置に置きます。
derived::derived(int i) : a(i)
{
// …
}