78 votes

Déclarer un objet avant de l'initialiser en c++

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 juste déclarer un hors conditionnel pour qu'il obtienne la bonne portée.

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

46voto

Greg Hewgill Points 356191

Vous ne pouvez pas déclarer une variable sans appeler un constructeur. Cependant, dans votre exemple, vous pouvez faire ce qui suit :

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

45voto

Joce Points 3720

Vous ne pouvez pas utiliser de références ici, car dès que vous sortez du périmètre, la référence pointe vers un objet qui sera supprimé.

Vraiment, vous avez deux choix ici :

1- Allez avec les pointeurs :

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

// ...
delete a;

ou avec un pointeur intelligent

#include <memory>

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

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

Personnellement, j'opterais pour l'option 2.

41voto

Uri Points 50687

Vous ne pouvez pas le faire directement dans C++ puisque l'objet est construit lorsque vous le définissez avec le constructeur par défaut.

Vous pouvez toutefois lancer un constructeur paramétré pour commencer par :

Animal a(getAppropriateString());

Ou vous pouvez 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)

18voto

Steve Fallows Points 4059

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

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

Je le suggère parce que j'ai travaillé dans des endroits où l'opérateur conditionnel était interdit. (Soupir !) Aussi, cela peut être étendu au-delà de deux alternatives très facilement.

8voto

paquetp Points 1286

Si vous voulez éviter la collecte des ordures, 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 la syntaxe. au lieu de ->, vous pouvez le faire après le code ci-dessus :

Animal& a = *p_a;

// do stuff with a. whatever

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X