web-dev-qa-db-ja.com

C ++で初期化する前にオブジェクトを宣言する

インスタンス化せずにC++で変数を宣言することは可能ですか?私はこのようなことをしたい:

Animal a;
if( happyDay() ) 
    a( "puppies" ); //constructor call
else
    a( "toads" );

基本的に、正しいスコープを取得するために、条件の外側を宣言したいだけです。

ポインタを使用せずにaをヒープに割り当てずにこれを行う方法はありますか?たぶん、参照で賢い何か?

45
Quantum7

デフォルトのコンストラクタでオブジェクトを定義するとオブジェクトが構築されるため、C++でこれを直接行うことはできません。

ただし、パラメーター化されたコンストラクターを実行して、次のことを開始できます。

Animal a(getAppropriateString());

または、実際に?: operator正しい文字列を決定します。 (更新:@Gregはこのための構文を提供しました。その答えを参照してください)

33
Uri

コンストラクターを呼び出さずに変数を宣言することはできません。ただし、この例では次のことができます。

Animal a(happyDay() ? "puppies" : "toads");
41
Greg Hewgill

ここで参照を使用することはできません。スコープから出るとすぐに、参照は削除されるオブジェクトを指すからです。

実際、ここには2つの選択肢があります。

1-ポインターで移動:

Animal* a;
if( happyDay() ) 
    a = new Animal( "puppies" ); //constructor call
else
    a = new Animal( "toads" );

// ...
delete a;

2- AnimalにInitメソッドを追加します。

class Animal 
{
public:
    Animal(){}
    void Init( const std::string& type )
    {
        m_type = type;
    }
private:
    std:string m_type;
};

Animal a;
if( happyDay() ) 
    a.Init( "puppies" );
else
    a.Init( "toads" );

私は個人的にオプション2を使用します。

21
joce

私はグレッグの答えを好みますが、これもできます:

char *AnimalType;
if( happyDay() ) 
    AnimalType = "puppies";
else
    AnimalType = "toads";
Animal a(AnimalType);

条件演算子が禁止されている場所で作業したため、これをお勧めします。 (ため息!)また、これは非常に簡単に2つの選択肢を超えて拡張できます。

16
Steve Fallows

ガベージコレクションを回避する場合は、スマートポインターを使用できます。

auto_ptr<Animal> p_a;
if ( happyDay() )
    p_a.reset(new Animal( "puppies" ) );
else
    p_a.reset(new Animal( "toads" ) );

// do stuff with p_a-> whatever.  When p_a goes out of scope, it's deleted.

それでも。 ->の代わりに構文を使用すると、上記のコードの後に​​これを実行できます。

Animal& a = *p_a;

// do stuff with a. whatever
7
paquetp

グレッグヒューギルの答えに加えて、他にもいくつかのオプションがあります。

コードの本体を関数に持ち上げます:

void body(Animal & a) {
    ...
}

if( happyDay() ) {
  Animal a("puppies");
  body( a );
} else {
  Animal a("toad");
  body( a );
}

(Ab)新しい配置を使用:

struct AnimalDtor {
   void *m_a;
   AnimalDtor(void *a) : m_a(a) {}
   ~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};

char animal_buf[sizeof(Animal)]; // still stack allocated

if( happyDay() )
  new (animal_buf) Animal("puppies");
else
  new (animal_buf) Animal("toad");

AnimalDtor dtor(animal_buf); // make sure the dtor still gets called

Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on
6
Logan Capaldo

最善の回避策は、ポインターを使用することです。

Animal a*;
if( happyDay() ) 
    a = new Animal( "puppies" ); //constructor call
else
    a = new Animal( "toads" );
1
rkadeFR