web-dev-qa-db-ja.com

デフォルトのメンバー値のベストプラクティス

クラスのヘッダーファイルでクラスメンバーのデフォルト値を設定するためにC++ 11コードを記述するとき、それは良い習慣ですか?

または、クラスのコンストラクタでこれを行う方が良いですか?

編集:

というのは:

foo.h

#include <string>

using std::string;

class Foo{
    private:
        string greet = "hello";
    public:
        Foo();
};

VS

foo.cpp(もちろん、必要なヘッダーファイルがありますが、クラス内の初期化はありません):

Foo::Foo(){
    greet = "hello";
}

どちらが優れているのですか?

62
Paul

クラスメンバが常に同じ初期値で初期化される場合は、重複を避けるために、イニシャライザをインラインにする必要があります。初期値がコンストラクターに依存する場合は、コンストラクター初期化リストに入れます。 (そして、あなたがしたように割り当てを使用しないでください。)

例:

class Foo
{
    bool done = false;   // always start like this
    int qty;
    Bar * p;

public:
    Foo()                        : qty(0),              p(nullptr)    { }
    Foo(int q, Bar * bp)         : qty(q),              p(bp)         { }
    explicit Foo(char const * s) : qty(std::strlen(s)), p(new Bar(s)) { }

    // ...
};

この架空の例では、メンバーdoneは常にfalseとして開始する必要があるため、初期化子をインラインで記述するのが最善です。他の2つのメンバーqtypは、3つの異なるコンストラクターのそれぞれで別々に初期化できるため、コンストラクターの初期化リスト内で初期化されます。

キュリオサム:インライン初期化子を提供すると、クラスでtrivial default constructorを使用できなくなります。

77
Kerrek SB

古いC++コンパイラとの互換性を維持する必要があるかどうかによって異なります。C++ 11を使用していない場合、コンストラクタのほとんどのメンバー(すべて非静的)を初期化する必要があります。さらに、多くの人は、デフォルトのctorを明示的に呼び出すことを意味する場合でも、すべてのメンバーを明示的に初期化することを推奨しています。通常、ヘッダーファイルではなくcppファイルに実装の詳細を配置する必要があります。したがって、例は次のようになります。

Example:
//foo.h

class Foo{
public: 
  Foo();
private:
  std::vector<int> vect;
};

//foo.cpp

Foo::Foo():vect(){
}

C++ 11では選択肢が増え、特に複数のcorがある場合はクラスメンバーイニシャライザーが非常に便利になります。詳細については、次のリンクを参照してください。 http://www.stroustrup.com/C++11FAQ.html#member-init

編集後:コードによると、C++ 11を使用しています。私の知る限りでは、新しい可能性に関する優れた実践に関する情報はほとんどありませんが、IMHO In classメンバーのイニシャライザは、初期化を1か所に集中するのに非常に便利です。

11
Martin

ヘッダーで初期化することには、コードをよりローカルで理解しやすくするという主な利点があります。また、入力の手間も省けます。

私の意見では、主な欠点は、コンストラクターにアクセスするためにより多くのヘッダーを含める必要があることです。単純な前方宣言では不十分で、コンパイルに時間がかかります。

2