Est-il possible de déclarer une variable en c ++ sans l'instancier? Je veux faire quelque chose comme ça:
Animal a;
if( happyDay() )
a( "puppies" ); //constructor call
else
a( "toads" );
Fondamentalement, je veux simplement déclarer un extérieur du conditionnel afin qu'il obtienne la bonne portée.
Existe-t-il un moyen de le faire sans utiliser de pointeurs et allouer a
sur le tas? Peut-être quelque chose d'intelligent avec des références?
Vous ne pouvez pas le faire directement en C++ car l'objet est construit lorsque vous le définissez avec le constructeur par défaut.
Vous pouvez cependant exécuter un constructeur paramétré pour commencer:
Animal a(getAppropriateString());
Vous pouvez également utiliser quelque chose comme ?: operator
pour déterminer la chaîne correcte. (Mise à jour: @Greg a donné la syntaxe pour cela. Voir cette réponse)
Vous ne pouvez pas déclarer une variable sans appeler un constructeur. Cependant, dans votre exemple, vous pouvez effectuer les opérations suivantes:
Animal a(happyDay() ? "puppies" : "toads");
Vous ne pouvez pas utiliser de références ici, car dès que vous seriez hors de portée, la référence pointerait vers un objet qui serait supprimé.
Vraiment, vous avez deux choix ici:
1- Allez avec des pointeurs:
Animal* a;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );
// ...
delete a;
2- Ajoutez une méthode 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" );
Je choisirais personnellement l'option 2.
Je préfère la réponse de Greg, mais vous pouvez également faire ceci:
char *AnimalType;
if( happyDay() )
AnimalType = "puppies";
else
AnimalType = "toads";
Animal a(AnimalType);
Je suggère cela parce que j'ai travaillé dans des endroits où l'opérateur conditionnel était interdit. (Soupir!) De plus, cela peut être étendu au-delà de deux alternatives très facilement.
Si vous voulez éviter le ramasse-miettes, vous pouvez utiliser un pointeur intelligent.
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.
Si vous souhaitez toujours utiliser le. syntaxe au lieu de ->, vous pouvez le faire après le code ci-dessus:
Animal& a = *p_a;
// do stuff with a. whatever
En plus de la réponse de Greg Hewgill, il existe quelques autres options:
Soulevez le corps principal du code dans une fonction:
void body(Animal & a) {
...
}
if( happyDay() ) {
Animal a("puppies");
body( a );
} else {
Animal a("toad");
body( a );
}
(Ab) Utiliser le placement nouveau:
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 meilleure solution consiste à utiliser le pointeur.
Animal a*;
if( happyDay() )
a = new Animal( "puppies" ); //constructor call
else
a = new Animal( "toads" );