|
メンバイニシャライザでの初期化順序
メンバイニシャライザを使うと、コンストラクタの呼び出し時にクラスメンバを初期化することができます。具体的な例を見てみましょう。次の例では、コンストラクタの引数で受け取ったid、keyでメンバを初期化しています。
// クラス定義
class MyClass
{
public:
MyClass(){}
MyClass(int id, int key) : m_id(id), m_key(key){}
virtual ~MyClass(){}
private:
int m_id;
int m_key;
};
// メイン関数
int main(int argc, char *argv[])
{
MyClass mc(1, 100);
return 0;
}
|
さて、この例ではm_id、m_keyの2つを初期化しました。この2つはコンストラクタの本体が実行される前に初期化されますが、ではどちらが先に初期化されるのでしょうか。これは、"宣言順"に初期化される決まりになっています。
宣言というのはこの部分です。
private:
int m_id;
int m_key;
|
この場合は、m_id、m_keyの順に初期化されます。通常はそれほど気にする必要はありませんが、次のような場合は注意が必要です。
MyClass(int id) : m_id(id), m_key(m_id *2){}
|
この場合、m_keyはm_idの値に依存するので、m_idが先に初期化されていないといけません。従ってm_idの宣言のほうを先に記述してしないといけなくなります。
さて、初期化される順序はメンバの宣言順になるので、メンバイニシャライザではどういう順序で書いても同じ結果になります。例えば次のように書いても同じです。
MyClass(int id) : m_key(m_id *2), m_id(id){}
|
しかし、このように宣言順と違う順序で書くと、gcc -Wallでは警告が出ます。(プログラマが上記の点を見落としている可能性があるからということでしょう。ちなみにVCでは出ません。)ですので、常にメンバの宣言順と合わせるようにしたほうが良いでしょう。
また、メンバイニシャライザでのメンバの依存関係がある場合は、宣言順を変えると影響が出る可能性があるので、一度書いたメンバの宣言はむやみに書き換えないようにしましょう。
|