1054

C#開発者として、私はコンストラクターを実行することに慣れています。

class Test {
    public Test() {
        DoSomething();
    }

    public Test(int count) : this() {
        DoSomethingWithCount(count);
    }

    public Test(int count, string name) : this(count) {
        DoSomethingWithName(name);
    }
}

C ++でこれを行う方法はありますか?

クラス名を呼び出して「this」キーワードを使用しようとしましたが、どちらも失敗します。

4

15 に答える 15

1402

C++11: はい!

C++11 以降には、これと同じ機能があります (委譲コンストラクターと呼ばれます)。

構文は C# とは少し異なります。

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {}
};

C++03: いいえ

残念ながら、C++03 でこれを行う方法はありませんが、これをシミュレートする方法が 2 つあります。

  1. デフォルトのパラメーターを使用して、2 つ (またはそれ以上) のコンストラクターを組み合わせることができます。

    class Foo {
    public:
      Foo(char x, int y=0);  // combines two constructors (char) and (char, int)
      // ...
    };
    
  2. init メソッドを使用して共通コードを共有します。

    class Foo {
    public:
      Foo(char x);
      Foo(char x, int y);
      // ...
    private:
      void init(char x, int y);
    };
    
    Foo::Foo(char x)
    {
      init(x, int(x) + 7);
      // ...
    }
    
    Foo::Foo(char x, int y)
    {
      init(x, y);
      // ...
    }
    
    void Foo::init(char x, int y)
    {
      // ...
    }
    

参照については、C++FAQ エントリを参照してください。

于 2008-11-21T10:04:17.963 に答える
129

はい、いいえ、C++ のバージョンによって異なります。

C++03 では、あるコンストラクターを別のコンストラクターから呼び出すことはできません (委任コンストラクターと呼ばれます)。

これは C++11 (別名 C++0x) で変更され、次の構文のサポートが追加されました:
( Wikipediaからの例)

class SomeType
{
  int number;
 
public:
  SomeType(int newNumber) : number(newNumber) {}
  SomeType() : SomeType(42) {}
};
于 2008-11-21T10:00:12.417 に答える
49

コンストラクターからコンストラクターを呼び出すことができると思います。コンパイルして実行します。私は最近、誰かがこれを行っているのを見て、Windows と Linux の両方で実行されました。

それはあなたが望むことをしません。内側のコンストラクターは、外側のコンストラクターが戻ると削除される一時的なローカル オブジェクトを作成します。それらも異なるコンストラクターである必要があります。そうしないと、再帰呼び出しを作成します。

参照: https://isocpp.org/wiki/faq/ctors#init-methods

于 2009-08-12T15:31:52.917 に答える
37

C++11 : はい!

C++11 以降には、これと同じ機能があります (委譲コンストラクターと呼ばれます)。

構文は C# とは少し異なります。

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {}
};

C++03 : いいえ

コンストラクターで親クラスのコンストラクターを呼び出すことができることを指摘する価値があります。

 class A { /* ... */ };
    
    class B : public A
    {
        B() : A()
        {
            // ...
        }
    };

ただし、C++03 までは、同じクラスの別のコンストラクターを呼び出すことはできません。

于 2008-11-22T06:36:13.657 に答える
23

C++11では、コンストラクターは別のコンストラクター オーバーロードを呼び出すことができます

class Foo  {
     int d;         
public:
    Foo  (int i) : d(i) {}
    Foo  () : Foo(42) {} //New to C++11
};

さらに、メンバーはこのように初期化することもできます。

class Foo  {
     int d = 5;         
public:
    Foo  (int i) : d(i) {}
};

これにより、初期化ヘルパー メソッドを作成する必要がなくなります。また、初期化されていない可能性のあるメンバーを使用しないように、コンストラクターまたはデストラクターで仮想関数を呼び出さないことをお勧めします。

于 2011-09-22T20:07:00.453 に答える
17

悪になりたい場合は、インプレースの「new」演算子を使用できます。

class Foo() {
    Foo() { /* default constructor deliciousness */ }
    Foo(Bar myParam) {
      new (this) Foo();
      /* bar your param all night long */
    } 
};

私にはうまくいくようです。

編集

@ElvedinHamzagic が指摘しているように、メモリを割り当てたオブジェクトが Foo に含まれていた場合、そのオブジェクトは解放されない可能性があります。これは事態をさらに複雑にします。

より一般的な例:

class Foo() {
private:
  std::vector<int> Stuff;
public:
    Foo()
      : Stuff(42)
    {
      /* default constructor deliciousness */
    }

    Foo(Bar myParam)
    {
      this->~Foo();
      new (this) Foo();
      /* bar your param all night long */
    } 
};

確かに、少しエレガントに見えません。@JohnIdolのソリューションははるかに優れています。

于 2011-03-24T16:53:45.940 に答える
11

いいえ、C++ では、コンストラクターからコンストラクターを呼び出すことはできません。ウォーレンが指摘したように、できることは次のとおりです。

  • 異なるシグネチャを使用してコンストラクターをオーバーロードする
  • 引数にデフォルト値を使用して、「より単純な」バージョンを利用可能にします

最初のケースでは、あるコンストラクターを別のコンストラクターから呼び出すことによってコードの重複を減らすことはできないことに注意してください。もちろん、すべての初期化を行う個別のプライベート/保護されたメソッドを作成し、コンストラクターに主に引数の処理を任せることもできます。

于 2008-11-21T09:56:18.400 に答える
7

まだ表示されていない別のオプションは、クラスを 2 つに分割し、元のクラスの周りに軽量のインターフェイス クラスをラップして、探している効果を実現することです。

class Test_Base {
    public Test_Base() {
        DoSomething();
    }
};

class Test : public Test_Base {
    public Test() : Test_Base() {
    }

    public Test(int count) : Test_Base() {
        DoSomethingWithCount(count);
    }
};

「次のレベルアップ」の相手を呼び出さなければならないコンストラクターが多数ある場合、これは面倒になる可能性がありますが、少数のコンストラクターの場合は実行可能です。

于 2011-11-25T00:54:11.947 に答える
5

Visual C ++では、コンストラクター内で次の表記を使用することもできます:this-> Classname :: Classname(別のコンストラクターのパラメーター)。以下の例を参照してください。

class Vertex
{
 private:
  int x, y;
 public:
  Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
  Vertex()
  {
   this->Vertex::Vertex(-1, -1);
  }
};

他の場所で機能するかどうかはわかりません。VisualC++2003と2008でのみテストしました。JavaやC#と同じように、この方法で複数のコンストラクターを呼び出すこともできます。

PS:率直に言って、これが以前に言及されていなかったことに私は驚いた。

于 2012-02-20T10:00:51.643 に答える
2

private friendコンストラクターのアプリケーション ロジックを実装し、さまざまなコンストラクターによって呼び出されるメソッドの使用を提案します。次に例を示します。

StreamArrayReaderいくつかのプライベート フィールドで呼び出されるクラスがあるとします。

private:
    istream * in;
      // More private fields

そして、2 つのコンストラクターを定義します。

public:
    StreamArrayReader(istream * in_stream);
    StreamArrayReader(char * filepath);
    // More constructors...

2 番目のものは最初のものを単純に利用します (もちろん、前者の実装を複製したくはありません)。理想的には、次のようなことをしたいでしょう:

StreamArrayReader::StreamArrayReader(istream * in_stream){
    // Implementation
}

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    StreamArrayReader(&instream);
    instream.close();
}

ただし、これは C++ では許可されていません。そのため、最初のコンストラクターが行うべきことを実装するプライベート フレンド メソッドを次のように定義できます。

private:
  friend void init_stream_array_reader(StreamArrayReader *o, istream * is);

これで、このメソッドは (フレンドであるため) のプライベート フィールドにアクセスできるようになりましたo。次に、最初のコンストラクターは次のようになります。

StreamArrayReader::StreamArrayReader(istream * is) {
    init_stream_array_reader(this, is);
}

これにより、新しく作成されたコピーに対して複数のコピーが作成されるわけではないことに注意してください。2 つ目は次のようになります。

StreamArrayReader::StreamArrayReader(char * filepath) {
    ifstream instream;
    instream.open(filepath);
    init_stream_array_reader(this, &instream);
    instream.close();
}

つまり、1 つのコンストラクターが別のコンストラクターを呼び出す代わりに、両方ともプライベート フレンドを呼び出します。

于 2014-11-02T00:19:49.997 に答える
0

私があなたの質問を正しく理解しているなら、あなたはC ++で複数のコンストラクターを呼び出すことができるかどうか尋ねていますか?

それがあなたが探しているものなら、いいえ-それは不可能です。

確かに、それぞれが一意の引数シグネチャを持つ複数のコンストラクターを作成し、新しいオブジェクトをインスタンス化するときに必要なコンストラクターを呼び出すことができます。

最後にデフォルトの引数を持つコンストラクターを1つ持つこともできます。

ただし、複数のコンストラクターがない場合は、それぞれを個別に呼び出します。

于 2008-11-21T09:49:40.923 に答える
0

コンストラクターを呼び出すと、実際にはスタックまたはヒープからメモリが割り当てられます。したがって、別のコンストラクターでコンストラクターを呼び出すと、ローカル コピーが作成されます。したがって、注目しているオブジェクトではなく、別のオブジェクトを変更しています。

于 2014-01-06T10:52:33.987 に答える