4

最近苦労していました。

問題はコンストラクターの呼び出しです。

次のようなコードを書きました。

#include <iostream>
using namespace std;

class Foo
{

  private: int _n;

  public:

  Foo() { Foo(5);}

  Foo(int n) {_n=n; cout << n << endl; }

};

int main()
{
   Foo* foo = new Foo();
   return 0;

}

デフォルトのコンストラクターを使用して外部で Foo オブジェクトを構築した場合:

Foo* f = new Foo();

変数 _n は 5 だと思いますが、そうではありません。

Java では問題ありませんが、C++ では問題ありません。

また、Visual C++ 6 sp 6 では、

Foo() {this->Foo(5);}

動作します。

ただし、この式は gcc/g++ 4 では拒否されます。

最後に、私は解決策を見つけました。

デフォルトのコンストラクターを単純に変更する

Foo() {Foo(5);}

の中へ

Foo() { new (this) Foo(5); }

問題を解決します。

括弧内の「これ」は何をしますか?

4

5 に答える 5

4

が行うこと(this)は、 が指す場所に真新しいFooオブジェクトを作成することthisです (これを新しい配置と呼びます)。charandの配列でのみ使用し、unsigned char他の場所では使用しないでください (また、そこにもほとんど使用しないでください)。Fooすでに構築を開始している場所にを構築しているためthis、未定義の動作が行われ、基本クラスがあればリソースがいたるところにリークします。歴史的に、通常行うべきことは、初期化をプライベート関数に移動することだけです。

class Foo {
public:    
  Foo() { init(5);}    
  Foo(int n) {init(n);}
private: 
  int _n;
  void init(int n) {
    _n=n;
  };
}

C++11 では、コンストラクターはこの構文で相互に呼び出すことができるはずですが、どのコンパイラーがそれをサポートしているかはまだわかりません。 Apache によると、GCC 4.7 と Clang 3.0 でサポートされていますが、Intel C++ と VC++ ではまだサポートされていません。

class Foo {
public:    
  Foo() : Foo(5) {}
  Foo(int n) {_n=n;}
private: 
  int _n;
}

開始したコードは、Foo() { Foo(5);}の構築を開始し、スタック上にパラメーター 5 を使用してthis真新しいオブジェクトを作成し、それを破棄して、独自の値を初期化することなく、完全に構築されたと見なします。Fooそのため、コンパイルして実行しましたが、何もしていないように見えました。

于 2012-07-18T18:50:09.537 に答える
3

C++11 では、委譲コンストラクターでこれを指定します。

Foo() : Foo(5) { }
于 2012-07-18T18:49:15.420 に答える
1

(this)括弧内は、new演算子thisクラスを初期化するためのアドレスとしてのアドレスを使用することを意味します。

これは非常に危険です。現在のオブジェクトのコンストラクターにいて、同じメモリ空間で新しいコンストラクターを呼び出します。別のクラスから継承するとどうなるか想像してみてください。

あなたの問題に関しては、コンストラクター内から別のオーバーロードされたコンストラクターを呼び出すことはできません。典型的な解決策は、クラスを初期化するメソッドを用意することです。

class Foo
{
  int _n;
public:
  Foo() { init(5); }
  Foo( int i) { init(i); }
  void init(int i) { _n = i; }
};

ここでもまったく同じ問題がありました。さらに別の C++ オブジェクトの初期化の尋問。自由に解決策を見てください。

于 2012-07-18T18:50:22.617 に答える
0
Foo() { new (this) Foo(5); }

事前に割り当てられたメモリでコンストラクターを呼び出す "placement new" 演算子です。

さて、他の質問について-C++ 11は正確にそれを許可します(コンストラクターを相互に呼び出す)が、以前の標準(特にMSVC 6で使用されるもの)にはそれがないため、これらの醜いinit()メソッドを使用する方法ですあなたのために行きます。

于 2012-07-18T18:49:12.150 に答える
0

C++ の正しい構文は次のとおりです。

class Foo { 

  private: int _n; 

  public: 

  Foo() : Foo(5) {} 

  Foo(int n) _n(n) {} // As suggested by another member's edit, initializer lists are preferred

};

または、C++ では、次のようなデフォルトのパラメーター値を使用できます。

Foo(int n = 5);

これにより、2 つではなく 1 つのコンストラクターを作成できます。

また、インライン関数と非インライン関数の違いについても知っておく必要があります。この Java スタイルのプログラミングは有効な C++ ですが、長所と短所があり、少なくとも 1 つの他の代替手段があります。

于 2012-07-18T18:46:48.343 に答える