11

私はこのC++オープンソースコードを読んでいて、コンストラクターに来ましたが、それを取得できません(基本的に、C ++を知らないためです:P)

私はCとJavaをよく理解しています。

 TransparentObject::TransparentObject( int w, int x, int y, int z ) : 
     _someMethod( 0 ),
     _someOtherMethod( 0 ),
     _someOtherOtherMethod( 0 ),
     _someMethodX( 0 ) 
  {
       int bla;
       int bla;
  }

私が「推測」できる限り、最初の行はコンストラクター名のみを宣言しています。「::」は私には「所属」のように聞こえます。そして、{}の間のコードは、それ自体がコンストラクター本体です。

パラメータの後にあるものを「考え」、最初の「{」はメソッドのデフォルトパラメータなどのようなものですが、Web上で合理的な説明が見つかりません。例で見つけたC++コンストラクターのほとんどは、Javaのものとほとんど同じです。

私は私の仮定で正しいですか?「::」はに属するようなものであり、paramsとbodyの後のリストは「defaultargs」などのようなものですか?

更新: 回答ありがとうございます。それらをメソッドと呼んでもいいですか?(私はノーだと思います)そしてコンストラクター本体内でそれらを呼び出すことの違いは何ですか

4

8 に答える 8

20

最も一般的なケースは次のとおりです。

class foo{
private:
    int x;
    int y;
public:
    foo(int _x, int _y) : x(_x), y(_y) {}
}

これにより、コンストラクターパラメーターで指定された値が設定xされます。これは、多くの場合、データメンバーとして宣言されているオブジェクトを作成するための最良の方法です。y_x_y

コンストラクターチェーンを調べていた可能性もあります。

class foo : public bar{
    foo(int x, int y) : bar(x, y) {}
};

この場合、クラスのコンストラクターはその基本クラスのコンストラクターを呼び出し、値xとを渡しますy

関数をさらに分析するには:

TransparentObject::TransparentObject( int w, int x, int y, int z ) : 
   _someMethod( 0 ),
   _someOtherMethod( 0 ),
   _someOtherOtherMethod( 0 ),
   _someMethodX( 0 ) 
{
     int bla;
     int bla;
}

-::演算子は、スコープ解決演算子と呼ばれます。基本的には、TransparentObjectがのメンバーであることを示していTransparentObjectます。第二に、コンストラクターの本体が中括弧で囲まれていると仮定するのは正しいです。

更新:回答ありがとうございます。それらをメソッドと呼んでもいいですか?(私はノーだと思います)そしてコンストラクター本体内でそれらを呼び出すことの違いは何ですか

このテーマについては、私がここで提供できるよりもはるかに多くの情報があります。初期化リストを使用する必要がある最も一般的な領域は、参照またはを初期化するときです。constこれらの変数には、作成直後に値を指定する必要があるためです。

于 2008-10-16T23:28:00.510 に答える
10

あなたはかなり近いです。最初の行は宣言です。::の左側のラベルはクラス名であり、コンストラクターであるためには、関数名はクラス名と同じである必要があります。

TransparentObject::TransparentObject( int w, int x, int y, int z )

C ++では、オプションで、関数本体の開始前に、メンバー変数のコロンといくつかの初期値を配置できます。const変数を初期化する場合、またはパラメーターをスーパークラスコンストラクターに渡す場合は、この手法を使用する必要があります。

: 
 _someMethod( 0 ),
 _someOtherMethod( 0 ),
 _someOtherOtherMethod( 0 ),
 _someMethodX( 0 )

次に、中括弧で囲まれたコンストラクターの本体があります。

{
   int bla;
   int bla;
}
于 2008-10-16T23:30:02.410 に答える
7

::実際にはcontainsを意味します(説明についてはコメントを参照)が、_someMethodsなどは初期化リストと呼ばれるものです。リンクにはたくさんの情報があります=]

編集:申し訳ありませんが、私の最初の文は正しくありません-コメントを参照してください。

于 2008-10-16T23:26:55.597 に答える
2

はい、::はC ++スコープ演算子であり、関数が何に属しているかをコンパイラーに通知できます。コンストラクター宣言の後に:を使用すると、いわゆる初期化リストが開始されます。

于 2008-10-16T23:27:14.490 に答える
2

引数リストと{}sの間のコードは、クラスメンバー(の一部)の初期化を指定します。

割り当てとは対照的な初期化---それらは異なるものです---したがって、これらはすべてコンストラクターへの呼び出しです。

于 2008-10-16T23:27:45.050 に答える
1

あなたは正しいです。クラス変数のデフォルト値を設定する方法です。:の後に置くことと関数本体に置くことの正確な違いについてはあまり詳しくありません。

于 2008-10-16T23:27:01.980 に答える
1

通常、初期化リストを使用する正当な理由がいくつかあります。1 つには、コンストラクターの初期化リストの外部で参照されているメンバー変数を設定することはできません。また、メンバー変数が独自のコンストラクターに特定の引数を必要とする場合は、ここでそれらを渡す必要があります。これを比較してください:

class A
{
public:
  A();
private:
  B _b;
  C& _c;
};

A::A( C& someC )
{
  _c = someC; // this is illegal and won't compile. _c has to be initialized before we get inside the braces
  _b = B(NULL, 5, "hello"); // this is not illegal, but B might not have a default constructor or could have a very 
                            // expensive construction that shouldn't be done more than once
}

このバージョンに:

A::A( C& someC )
: _b(NULL, 5, "hello") // ok, initializing _b by passing these arguments to its constructor
, _c( someC ) // this reference to some instance of C is correctly initialized now
{}
于 2008-11-30T17:13:20.140 に答える
0

初期化子リストを使用しないと、すべてのクラス メンバーはデフォルトのコンストラクターを呼び出すだけなので、どのコンストラクターを呼び出すかを制御できるのはここだけです (動的に割り当てられていないメンバーの場合)。どの親クラスのコンストラクターが呼び出されるかについても同様です。

コンストラクターの本体内 (つまり、= 演算子を使用した {} 中括弧の間) で "初期化" されたクラス メンバーは、技術的には初期化ではなく、代入です。自明ではないコンストラクター/デストラクターを持つクラスの場合、デフォルトの構成を構築してから、このように代入によって変更するとコストがかかる可能性があります。参照メンバーの場合、代入演算子を介して変更できないため、初期化子リストを使用する必要があります。

メンバー (または親クラス) に既定のコンストラクターがない場合、初期化子リストで適切なコンストラクターを指定しないと、コンパイラでエラーが生成されます。それ以外の場合、コンパイラはデフォルトのコンストラクター呼び出し自体を挿入します。組み込み型の場合、これは何もしないため、そこにガベージ値が含まれます。

初期化子リストでメンバーを指定する順序は、それらが呼び出される順序には影響しないことに注意してください。常に親クラス コンストラクター (存在する場合) が最初で、次にクラス定義で定義されている順序でクラス メンバーになります。それらをイニシャライザリストに入れる順序は重要ではなく、微妙なバグの原因になる可能性があります...

m_b以下の不自然な例では、 で初期化してから で初期化するつもりのように見えますが、実際には で初期化され(valueそれ自体はまだ初期化されていません)、で初期化されます。ゴミが入るだけ!m_am_bm_am_bm_bvaluem_b

struct BadInitialiserListExample
{
    BadInitialiserListExample(int value) :
        m_b(value),
        m_a(m_b)      // <-- *BUG* this is actually executed first due to ordering below!
    {
    }

    int    m_a;
    int    m_b;
};
于 2011-11-12T13:02:22.387 に答える