76

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

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

基本的に、条件の外側を宣言して、適切なスコープを取得したいだけです。

ポインターを使用せずaにヒープに割り当てる方法はありますか? 多分参照で賢い何か?

4

10 に答える 10

45

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

Animal a(happyDay() ? "puppies" : "toads");
于 2009-04-29T00:21:16.443 に答える
43

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

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

1-ポインターを使用します:

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

// ...
delete a;

またはスマートポインターを使用して

#include <memory>

std::unique_ptr<Animal> a;
if( happyDay() ) 
    a = std::make_unique<Animal>( "puppies" );
else
    a = std::make_unique<Animal>( "toads" );

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

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を使用します。

于 2009-04-29T00:27:42.310 に答える
40

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

ただし、最初にパラメーター化されたコンストラクターを実行できます。

Animal a(getAppropriateString());

または、実際に のようなものを使用して?: operator、正しい文字列を決定することもできます。(更新:@Gregはこれの構文を提供しました。その回答を参照してください)

于 2009-04-29T00:23:36.813 に答える
18

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

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

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

于 2009-04-29T00:35:50.607 に答える
8

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

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
于 2009-04-29T01:05:58.973 に答える
1

std::move も使用できます。

class Ball {
private:
        // This is initialized, but not as needed
        sf::Sprite ball;
public:
        Ball() {
                texture.loadFromFile("ball.png");
                // This is a local object, not the same as the class member.
                sf::Sprite ball2(texture);
                // move it
                this->ball=std::move(ball2);
        }
...
于 2020-03-21T09:02:37.017 に答える
-5

はい、次のことができます。

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

これにより、コンストラクターが適切に呼び出されます。

編集:1つ忘れていました... aを宣言するときは、何もしないコンストラクターであるか、値を初期化するコンストラクターであるかにかかわらず、コンストラクターを呼び出す必要があります。したがって、このメソッドは 2 つのオブジェクトを作成します。1 つは初期化時、もう 1 つは if ステートメント内です。

より良い方法は、次のようなクラスの init() 関数を作成することです。

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

この方法はより効率的です。

于 2009-04-29T00:21:08.957 に答える