2017-07-14 3 views
2

非常に簡単なような問題が発生しているため、何かを見落とさなくてはなりません。イニシャライザリストの外でフィールドを初期化できません

クラス(非POD)であるフィールドを持つクラスを作成する必要があります。フィールドのクラスには、デフォルトのコンストラクタと "実際の"コンストラクタがあります。実際には、コンストラクタには、いくらか複雑なループを満たす必要のあるパラメータがあるため、イニシャライザリストにフィールドを実際に構築することはできません。

これは、問題を再現する最小限の例です。

ConstructorsTest.h:

class SomeProperty { 
public: 
    SomeProperty(int param1); //Ordinary constructor. 
    SomeProperty();   //Default constructor. 
    int param1; 
}; 

class ConstructorsTest { 
    ConstructorsTest(); 
    SomeProperty the_property; 
}; 

ConstructorsTest.cpp:

#include "ConstructorsTest.h" 

ConstructorsTest::ConstructorsTest() { 
    the_property(4); 
} 

SomeProperty::SomeProperty(int param1) : param1(param1) {} 
SomeProperty::SomeProperty() : param1(0) {} //Default constructor, doesn't matter. 

しかし、これはコンパイルエラーを与える:

ConstructorsTest.cpp: In constructor 'ConstructorsTest::ConstructorsTest()': 
ConstructorsTest.cpp:4:19: error: no match for call to '(SomeProperty) (int)' 
    the_property(4); 
       ^

それは通常何のだろうそれのような何の示唆を与えていません代わりに機能を意図している可能性があります。

上記の例では、初期化リストでthe_propertyを初期化するだけですが、実際には4は実際には最初に生成する必要がある複雑なベクターなので実際にはできません。 the_property(4)を初期化子リストに移動すると、コンパイルが成功します。

オブジェクトにはdefault constructor、またはit can't be constが必要です。両方の要件がここで満たされているようです。

答えて

2

データメンバをコンストラクタの本体内で初期化することはできません。 (the_property(4);だけファンクタとしてthe_propertyを起動しようとしている。)のようにあなたがそれらだけを割り当てることができます。あなたは、必要なデータを生成するメンバ関数を追加し、データメンバを初期化するために使用することができ

ConstructorsTest::ConstructorsTest() { 
    the_property = ...; 
} 

but in reality the 4 is actually a complex vector that needs to be generated first

member initializer listにあります。例えば

class ConstructorsTest { 
    ... 
    static int generateData(); 
}; 

int ConstructorsTest::generateData() { 
    return ...; 
} 

ConstructorsTest::ConstructorsTest() : the_property(generateData()) { 
} 
+0

ああ、実際にはそれらを '='で割り当てることです。私はそれが何か簡単であることを知っていた! – Ghostkeeper

+0

@Ghostkeeper代入手法は、デフォルトでデータ・メンバーを作成し、それをコンストラクターの本体に割り当てると、メンバー・イニシャライザー・リストを使用するより効率が悪く、データ・メンバーを直接(割り当てなしで)構成します。 – songyuanyao

0

あなたは二回変数を初期化することはできません。 コンストラクタが起動すると、すべてメンバサブオブジェクトが構築されます。コンストラクタにメンバー初期化子を指定しないか、クラス定義のデフォルトのメンバー初期化子を指定しないと、デフォルトの初期化が実行されます。それがどんな形をとっても、あなたはそれをもう一度作ることはできません。

複雑な複数文の初期化は、最良のラムダ関数を介して行われます。

ConstructorsTest::ConstructorsTest() 
    : the_property([]{ /* Do Complex Initialization */}()) 
{ 
} 

:うーん...することができますが、ないような。そして、あなたは本当にこれほど単純なケースではいけません。

関連する問題