Question

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" );

En gros, je veux simplement déclarer un élément extérieur au conditionnel afin d'obtenir la bonne portée.

Y a-t-il un moyen de le faire sans utiliser de pointeurs ni allouer à sur le tas? Peut-être que quelque chose d'intelligent avec des références?

Était-ce utile?

La solution

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 toutefois exécuter un constructeur paramétré pour commencer:

Animal a(getAppropriateString());

Vous pouvez également utiliser quelque chose comme l'opérateur ?: pour déterminer la chaîne correcte. (Mise à jour: @Greg a donné la syntaxe. Voir la réponse.)

Autres conseils

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 sortiriez de la 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- Ajouter 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" );

J'irais personnellement avec l'option 2.

Je préfère la réponse de Greg, mais vous pouvez également le faire:

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!) En outre, cela peut être étendu très facilement au-delà de deux alternatives.

Si vous souhaitez éviter la récupération de place, 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

Outre la réponse de Greg Hewgill, il existe quelques autres options:

Soulevez le corps 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 un pointeur.

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

Oui, vous pouvez procéder comme suit:

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

Cela appellera les constructeurs correctement.

EDIT: Oublié une chose ... Lorsque vous déclarez un, vous devez toujours appeler un constructeur, qu’il s’agisse d’un constructeur qui ne fait rien ou qui initialise toujours les valeurs. Cette méthode crée donc deux objets, l'un à l'initialisation et l'autre à l'intérieur de l'instruction if.

Une meilleure solution consiste à créer une fonction init () de la classe, telle que:

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

Cette méthode serait plus efficace.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top