コンストラクタ内のコロンの後のメンバー変数リストは何に適していますか?
-
03-07-2019 - |
質問
この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;
}
「推測」できる限り最初の行は、コンストラクター名、" ::"のみを宣言します。 「〜に属する」のように聞こえます。私に。そして、{}の間のコードは、コンストラクター本体です。
私は「考える」パラメーターと最初の" {"の後はメソッドのデフォルトパラメータなどに似ていますが、ウェブ上で合理的な説明は見つかりません。例で見つけたC ++コンストラクターのほとんどは、Javaのものとほとんど同じです。
私は自分の仮定に合っていますか? " ::"のようなもので、paramsとbodyの後のリストは" default args"のようなものです。または何か?
更新: 答えてくれてありがとう。 それらはメソッドと呼ばれますか? (私は推測しません)、コンストラクタ本体内でそれらを呼び出すことの違いは何ですか
解決
最も一般的なケースは次のとおりです:
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;
}
::
-operatorはスコープ解決演算子と呼ばれます。基本的には、 TransparentObject
が TransparentObject
のメンバーであることを示しています。第二に、コンストラクタの本体が中括弧内にあると仮定するのは正しいことです。
更新:答えてくれてありがとう。それらはメソッドと呼ばれますか? (私は推測しません)、コンストラクタ本体内でそれらを呼び出すことの違いは何ですか
このテーマに関する情報は、私がこれまでに提供していたよりもはるかに多くありますこちら。初期化子リストを使用する必要がある最も一般的な領域は、参照または const
を初期化するときです。これらの変数には、作成直後に値を指定する必要があるためです。
他のヒント
かなり近いです。最初の行は宣言です。 ::の左のラベルはクラス名であり、コンストラクターであるためには、関数名はクラス名と同じである必要があります。
TransparentObject::TransparentObject( int w, int x, int y, int z )
C ++では、必要に応じて、関数本体の開始前にコロンとメンバー変数の初期値を配置できます。 const 変数を初期化する場合、またはスーパークラスコンストラクターにパラメーターを渡す場合は、この手法を使用する必要があります。
:
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
次に、コンストラクターの本体が中括弧で囲まれます。
{
int bla;
int bla;
}
::実際には次を含むことを意味します(説明はコメントを参照してください)。ただし、_someMethodsなどは初期化リスト。リンクには多くの情報があります=]
編集:申し訳ありませんが、私の最初の文は間違っています-コメントをご覧ください。
はい、:: C ++スコープ演算子で、コンパイラーに関数の所属を伝えることができます。 :を使用して、コンストラクター宣言が初期化リストと呼ばれるものを開始します。
引数リストと {}
sの間のコードは、クラスメンバー(の一部)の初期化を指定します。
割り当てではなく初期化---それらは異なるものです---これらはすべてコンストラクターの呼び出しです。
あなたは正しいです。クラス変数のデフォルト値を設定する方法。 :の後に置くことと関数の本体に置くことの正確な違いにあまり詳しくありません。
通常、初期化リストを使用する理由はいくつかあります。 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
{}
イニシャライザリストを使用しない場合、すべてのクラスメンバーは単にデフォルトコンストラクターが呼び出されるため、これがどのコンストラクターを制御できる唯一の場所です(動的に割り当てられていないメンバーの場合)。親クラスコンストラクターが呼び出される場合も同様です。
クラスメンバー" initialized"コンストラクターの本体内(つまり、=演算子を使用した{}中括弧内)は技術的に初期化されていません。これは割り当てです。自明でないコンストラクタ/デストラクタを持つクラスの場合、デフォルトのコンストラクトを作成してからこの方法で割り当てを変更するとコストが高くなる可能性があります。参照メンバーの場合、割り当て演算子を使用して変更できないため、初期化リストを使用する必要があります 。
メンバー(または親クラス)にデフォルトのコンストラクターがない場合、初期化リストで適切なコンストラクターを指定しないと、コンパイラーがエラーを生成します。そうでない場合、コンパイラーはデフォルトのコンストラクター呼び出しを挿入します。組み込み型の場合、これは何もしないため、ガベージ値があります。
初期化リストでメンバーを指定する順序は、メンバーの呼び出し順序に影響しないことに注意してください。常に最初に親クラスコンストラクター(存在する場合)が最初になり、次にクラス定義で定義された順序でクラスメンバーになります。初期化リストにそれらを置く順序は重要ではなく、微妙なバグの原因になる可能性があります...
下の不自然な例では、 value
で m_b
を初期化し、次に m_b
で m_a
を初期化することが意図されているようです。 >しかし、実際に起こるのは、 m_a
が m_b
(それ自体はまだ初期化されていない)で初期化され、次に m_b
がで初期化されることです値
。 m_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;
};