Domanda

È possibile dichiarare una variabile in c ++ senza istanziarla? Voglio fare qualcosa del genere:

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

Fondamentalmente, voglio solo dichiarare un esterno al condizionale in modo che ottenga lo scopo giusto.

Esiste un modo per farlo senza usare i puntatori e allocare a sull'heap? Forse qualcosa di intelligente con riferimenti?

È stato utile?

Soluzione

Non puoi farlo direttamente in C ++ poiché l'oggetto viene costruito quando lo definisci con il costruttore predefinito.

Tuttavia, è possibile eseguire un costruttore con parametri per iniziare:

Animal a(getAppropriateString());

Oppure potresti effettivamente usare qualcosa come ?: operator per determinare la stringa corretta. (Aggiornamento: @Greg ha fornito la sintassi per questo. Vedi quella risposta)

Altri suggerimenti

Non puoi dichiarare una variabile senza chiamare un costruttore. Tuttavia, nel tuo esempio potresti fare quanto segue:

Animal a(happyDay() ? "puppies" : "toads");

Non è possibile utilizzare i riferimenti qui, poiché non appena si esce dall'ambito, il riferimento punta a un oggetto che verrà eliminato.

Davvero, hai due scelte qui:

1- Vai con i puntatori:

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

// ...
delete a;

2- Aggiungi un metodo Init a 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" );

Vado personalmente con l'opzione 2.

Preferisco la risposta di Greg, ma potresti anche farlo:

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

Lo suggerisco perché ho lavorato in luoghi in cui era vietato l'operatore condizionale. (Sospiro!) Inoltre, questo può essere ampliato molto facilmente oltre due alternative.

Se vuoi evitare la garbage collection, puoi usare un puntatore intelligente.

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.

Se vuoi ancora usare il. sintassi invece di - > ;, puoi farlo dopo il codice sopra:

Animal& a = *p_a;

// do stuff with a. whatever

Oltre alla risposta di Greg Hewgill, ci sono alcune altre opzioni:

Estrai il corpo principale del codice in una funzione:

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

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

(Ab) Usa posizionamento nuovo:

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

La soluzione migliore è utilizzare il puntatore.

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

Sì, puoi fare quanto segue:

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

Questo chiamerà correttamente i costruttori.

EDIT: ho dimenticato una cosa ... Quando dichiari un, dovrai chiamare ancora un costruttore, che si tratti di un costruttore che non fa nulla o che inizializza comunque i valori a qualunque cosa. Questo metodo crea quindi due oggetti, uno all'inizializzazione e l'altro all'interno dell'istruzione if.

Un modo migliore sarebbe quello di creare una funzione init () della classe, come ad esempio:

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

In questo modo sarebbe più efficiente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top