web-dev-qa-db-ja.com

コンストラクタ初期化子リストで関数を呼び出しても大丈夫ですか?

私の直感はそうではありません。私は次の状況にあります:

class PluginLoader
{
   public:
      Builder* const p_Builder;
      Logger* const p_Logger;

      //Others
};

PluginLoader::PluginLoader(Builder* const pBuilder)
   :p_Builder(pBuilder), p_Logger(pBuilder->GetLogger())
{
   //Stuff
}

または、コンストラクタを変更してLogger* constPluginLoaderはどこから構築されますか?

33
nakiya

それは完全に正常で正常です。 p_Builderはその前に初期化されました。

36
GManNickG

あなたが持っているものは結構です。しかし、私はあなたに注意するように警告したいだけですこれをしないこと:(これについて言及されたGMan、私はそれを完全に明確にしたかっただけです)

class PluginLoader
{
   public:
      Logger* const p_Logger;   // p_Logger is listed first before p_Builder
      Builder* const p_Builder;

      //Others
};

PluginLoader::PluginLoader(Builder* const pBuilder)
   :p_Builder(pBuilder),
    p_Logger(p_Builder->GetLogger())   // Though listed 2nd, it is called first.
                                       // This wouldn't be a problem if pBuilder 
                                       // was used instead of p_Builder
{
   //Stuff
}

コードに2つの変更を加えたことに注意してください。まず、クラス定義で、p_Builderの前にp_Loggerを宣言しました。次に、パラメーターではなく、メンバーp_Builderを使用してp_Loggerを初期化しました。

これらの変更はどちらでも問題ありませんが、p_Loggerが最初に初期化され、初期化されていないp_Builderを使用して初期化するため、一緒にバグが発生します。

メンバーは、クラス定義に現れる順序で初期化されることを常に覚えておいてください。また、それらを初期化リストに入れる順序は関係ありません。

23

完全に良い習慣です。

私はこれを提案します(しかしそれは純粋に個人的なレベルです):

柔軟性の目的でのみ、後で他のコンストラクターを作成する必要がある場合にのみ、コンストラクターで関数を呼び出す代わりに、それらをinit関数にグループ化します。

1
Jason Rogers