40

コンストラクターチェーンについての私の理解は、クラスに複数のコンストラクター(オーバーロードされたコンストラクター)があり、そのうちの1つが別のコンストラクターを呼び出そうとすると、このプロセスはCONSTRUCTOR CHAININGと呼ばれ、C++ではサポートされないということです。最近、オンライン資料を読んでいるときにこの段落に出くわしました。

クラスをデフォルト値に再初期化するためのメンバー関数を記述したい状況に陥る可能性があります。おそらくすでにこれを行うコンストラクターがあるため、メンバー関数からコンストラクターを呼び出そうとする誘惑に駆られるかもしれません。前述のように、コンストラクター呼び出しの連鎖はC++では不正です。関数内のコンストラクターからコードをコピーすることもできますが、これは機能しますが、コードが重複することになります。この場合の最善の解決策は、コードをコンストラクターから新しい関数に移動し、コンストラクターに関数を呼び出してデータを初期化する作業を実行させることです。

コンストラクターを呼び出すメンバー関数もコンストラクターチェーンの対象になりますか?C++でこのトピックに光を当ててください。

4

5 に答える 5

35

C ++ 11では、コンストラクターの連鎖が可能です(部分的に)。この機能は「コンストラクターの委任」と呼ばれます。したがって、C ++ 11では、次のことができます。

class Foo
{
public:
    Foo(int a) : Foo() { _a = a; }
    Foo(char* b) : Foo() { _b = b; }
    Foo() { _c = 1.5; }
private:
    int _a = 0;
    char* _b = nullptr;
    double _c;
};

ただし、別のコンストラクターを呼び出すコンストラクターは、他のメンバーを初期化できないという厳しい制限があります。したがって、委任コンストラクターを使用して次のことを行うことはできません。

class Foo
{
public:
    Foo(int a) : Foo(), _a(a) { }
    Foo(char* b) : Foo(), _b(b) { }
    Foo() { _c = 1.5; }
private:
    int _a = 0;
    char* _b = nullptr;
    double _c;
};

後者のコード例では、MSVC ++ 2013でコンパイルエラー「C3511:委任コンストラクターの呼び出しが唯一のメンバー初期化子になります」が表示されます。

于 2015-10-22T07:10:30.983 に答える
22

段落は基本的にこれを言います:

class X
{
   void Init(params) {/*common initing code here*/ }
   X(params1) { Init(someParams); /*custom code*/ } 
   X(params2) { Init(someOtherParams); /*custom code*/ } 
};

メンバー関数からコンストラクターを呼び出すこともできません。あなたはそれをやったように見えるかもしれませんが、それは幻想です:

class X
{
public:
    X(int i):i(i){}
    void f()
    {
       X(3); //this just creates a temprorary - doesn't call the ctor on this instance
    }
    int i;
};

int main()
{
    using std::cout;
    X x(4);
    cout << x.i << "\n"; //prints 4
    x.f();
    cout << x.i << "\n"; //prints 4 again
}
于 2011-09-08T14:01:46.463 に答える
3

それはテキストが言っていることではありません。これは、コンストラクターが正常で正当なメンバー関数を呼び出すことを示唆しています。これは、ctorを再度明示的に呼び出さないようにするため、およびctorとreset関数の間でコードが重複しないようにするためです。

Foo::Foo() {
  Init();
}

void Foo::Reset() {
  Init();
}

void Foo::Init() {
  // ... do stuff ...
}
于 2011-09-08T13:58:56.713 に答える
0

(メンバー関数からコンストラクターを呼び出す)が機能するかどうかはわかりませんが、これは悪い習慣です。初期化コードを新しい関数に移動するのが論理的な方法です。

基本的に、コンストラクターを作成しない限り、コンストラクターを呼び出さないでください...

于 2011-09-08T14:00:37.027 に答える
-2

メンバー関数からコンストラクターを呼び出すと、そのタイプのオブジェクトが一時的に作成されます。派生クラス関数を呼び出している場合、関数がスコープ外になると、すべての親コンストラクターも実行され、デストラクタを使用して破棄されます。

派生したすべてのクラスのオブジェクトを作成するため、メンバー関数でコンストラクターを呼び出すことはお勧めできません。

于 2013-11-16T01:34:57.847 に答える