2016-04-22 7 views
2

は私の質問の例です:派生クラスのコンストラクタは、イニシャライザのリストでベースのデフォルトコンストラクタを使用する必要がありますか?ここ

class MyBaseClass 
{ 
public: 
    MyBaseClass(): my_bool(false), my_value(0) 
    {} 
    MyBaseClass(bool b, int i): my_bool(b), my_value(i) 
    {} 

private: 
    bool my_bool; 
    int my_value; 
} 

class MyDerivedClass1 : public ::MyBaseClass 
{ 
public: 
    MyDerivedClass1(double d): my_double(d) 
    {} 
private: 
    double my_double; 
} 

class MyDerivedClass2 : public ::MyBaseClass 
{ 
public: 
    MyDerivedClass2(double d): MyBaseClass(), my_double(d) 
    {} 
private: 
    double my_double; 
} 

なぜMyDerivedClass1は明示的MyDerivedClass2中のような基本クラスを初期化する必要が対私の派生クラスを初期化しても大丈夫な方法ではないでしょうか?

なぜ私は基本コンストラクタを呼び出すだけでC++に頼ることができないのでしょうか?私は彼らが何かに初期化されたかどうかを知っている私は私の初期化リストで他のコンストラクタを呼び出す必要があるだろうが、私が欲しいのは、とにかく呼び出すベースのコンストラクタです。

+0

あなたはエラーを取得していますか?ベースコンストラクタを呼び出すと、コンパイラは自動的にベースクラスのデフォルトコンストラクタを呼び出す必要があります。 – NathanOliver

+0

@NathanOliver - いいえ私はエラーを取得していません。私はコードレビューで、MyDerivedClass2のような基本コンストラクタを含めるように言われました。なぜ私はその理由を尋ねました。誰も私に "ドキュメンテーション"が足りない正当な理由を与えることはできません。だから私はなぜここに尋ねている。また、ベストプラクティスについてのgoogleは、ベースコンストラクタを呼び出すと言いますが、私の同僚もその理由を決めましたが、なぜこの場合はどうすればいいのか分かりません。私は誰かがなぜ良い理由があることを望んでいた。 – TWhite

+3

これはコーディングの標準的な問題のように聞こえるでしょう。その場合、答えはおそらく "あなたがそれを考慮し、ベースを構成するデフォルトが適切で、それを忘れていないと判断したことを示しています" –

答えて

4

初期設定リストにデフォルトで構築された基本クラスを提供するかどうかに違いはありません。あなたのスタイルを完全に使用しているもの。 (または会社)

一般に、メンバを常に初期化すると仮定すると、2つのオプションがあります(コンストラクタを範囲外に保ちましょう)。

オプション1: init-listのすべてのメンバーを初期化します。

このオプションは、C++ 98と互換性がある場合に使用します。 1つのリストにすべての構築パラメータを定義しておくと、検索が容易になるという利点があります。 (あなたが50人以上のメンバーを持たない限り)

複数のコンストラクタを持つ場合、このオプションの欠点は非常に重複しています。これにより

、あなたが彼らのために3つのバリアント持つことができます。それはあなたがそれを「忘れる」ことを意図しているかどうかを確認するのは難しいものの

  • はデフォルトの初期化クラスをスキップし、このリストは短くなります。 (それにptrがクラスを置き換える考える)
  • デフォルトすべてのメンバーを初期化し、これは長いリストを作成し、しかし明示的にコピーがtempuary
でcontructingによって、あなたが初期化されているクラスを提供意思
  • 明確に示し、

    オプション2:は宣言ですべてのメンバーを初期化し、コンストラクタのパラメータを除く

    このオプションでは、クラス宣言内のすべてを初期化を前提としています。しかし、やはり明示的にデフォルトのコンストラクタを呼び出すことができます。丸い中カッコは関数宣言として解釈されるため、braced initを使用することができます。

    イニシャライザーリストでは、構成パラメーターにリンクされているメンバーを置くだけで済みます。

    このオプションの利点は、読み易さです(特に大きなクラスの場合)。これは、コンパイラのオプションを「最新の」コンパイラに制限するという欠点があります。

    基本クラス

    我々は再び基底クラスを考えると、彼らはメンバーであるかのようにそれらを見てみると、一貫性のある方法は、オプション1のために明示的にそれらを宣言するだろうし、オプション2のためにそれらを書いてはいけません。

    個人的に私はオプション2が好きです。私はあまりにも多くのメンバーを持つクラスに遭遇することが多く、すべてのメンバーが初期化されているかどうかを確認するのは、これで簡単です。

    オプション1は、コードを一貫性を保つためにレガシーのためによく使用されます。

    POD

    言及する重要

    あなたがそれらを初期化しない場合は、いくつかのランダムなデータを取得する ...ダブル、int型のように、PODを(昔ながらのデータ型)です。これにより、使用するメソッドに関係なく、明示的に初期化することが重要になります。

    結論だから最後に、それは無い機能的な違いを持つスタイルのすべての問題です。

  • 2

    ほとんどの場合、意味的な違いはなく、主にスタイルの1つですが、基本クラスのデフォルトのコンストラクタがユーザー提供でない場合は、違いがあります。

    違いは、メンバー初期化子リストにないベースであるという事実から来ているデフォルトの初期化Base()がそれをを価値の初期化明示的に書きながら、を、デフォルトコンストラクタのISN」の場合、ゼロ初期化を行い、ユーザーが提供する。

    したがって:

    struct A { int i; }; 
    struct B : A { 
        B() : j(i) {} // may be undefined behavior 
        int j; 
    }; 
    
    struct C : A { 
        C() : A(), j(i) {} // OK; both i and j are zero 
        int j; 
    }; 
    
    +0

    私はいつもゼロでしょうか?このコンパイラは独立していますか? – TWhite

    +0

    私は初期化されますか?デフォルトのコンストラクタはスキップしませんか? – JVApen

    関連する問題