web-dev-qa-db-fra.com

Portée des variables dans les déclarations if

J'ai une classe qui n'a ni constructeur par défaut ni opérateur d'affectation. Elle est donc déclarée et initialisée dans une instruction if/else en fonction du résultat d'une autre fonction. Mais ensuite, il est indiqué qu'il sera hors de portée ultérieurement, même si les deux routes du conditionnel créeront une instance. 

Prenons l'exemple suivant (réalisé avec int juste pour illustrer ce point):

#include <iostream>

int main() 
{
  if(1) {
    int i = 5;
  } else {
    int i = 0;
  }

  std::cout << i << std::endl;
  return 0;
}

Les variables déclarées dans un conditionnel sortent-elles du champ à la fin du conditionnel? Quelle est la bonne façon de gérer la situation dans laquelle il n'y a pas de constructeur par défaut mais où les arguments du constructeur dépendent de certaines conditions?

Modifier

À la lumière des réponses données, la situation étant plus complexe, l'approche devrait peut-être changer. Il existe une classe de base abstraite A et deux classes B et C qui dérivent de A. Comment cela pourrait-il ressembler à ceci:

if(condition) {
   B obj(args);
} else {
   C obj(args);
}

changer l'approche? Puisque A est abstrait, je ne pouvais pas simplement déclarer A* obj et créer le type approprié avec new

24
tpg2114

"Les variables déclarées dans un conditionnel sortent-elles du champ à la fin du conditionnel?"

Oui - la portée d'une variable locale est uniquement comprise entre crochets:

{
   int x; //scope begins

   //...
}//scope ends
//x is not available here

Dans votre cas, disons que vous avez class A.

Si vous ne traitez pas de pointeurs:

A a( condition ? 1 : 2 );

ou si vous utilisez un prototype de constructeur différent:

A a = condition ? A(1) : A(2,3);

Si vous créez l'instance sur le tas:

A* instance = NULL;
if ( condition = true )
{
   instance = new A(1);
}
else
{
   instance = new A(2);
}

ou vous pouvez utiliser l'opérateur ternaire:

//if condition is true, call A(1), otherwise A(2)
A* instance = new A( condition ? 1 : 2 );

MODIFIER:

Oui vous pourriez:

A* x = NULL; //pointer to abstract class - it works
if ( condition )
   x = new B();
else
   x = new C();

MODIFIER:

Il semble que ce que vous cherchiez, c’est le modèle d’usine (regardez-le)

 class A; //abstract
 class B : public A;
 class C : public A;

 class AFactory
 {
 public:
    A* create(int x)
    {
       if ( x == 0 )
          return new B;
       if ( x == 1 )
          return new C;
       return NULL;
    }
 };
21
Luchian Grigore

Les variables déclarées dans un conditionnel sortent-elles de la portée à la fin de le conditionnel?

Oui.

Quelle est la bonne façon de gérer la situation où il n'y a pas constructeur par défaut, mais les arguments du constructeur dépendent de certains conditionnels?

Ecrivez une fonction qui renvoie une valeur à partir de laquelle vous copiez.

T foo()
{
    if(condition)
        return T(x);
    return T(y);
}

void bar()
{
    T i(foo());
}

Modifier:

Puisque A est abstrait, je ne pourrais pas simplement déclarer A * obj et créer le type approprié avec nouveau.

Que voulez-vous dire? C'est exactement comment fonctionne la frappe dynamique. Sauf que je n'utiliserais pas de pointeur brut, j'utiliserais un unique_ptr.

std::unique_ptr<A> obj;
if(condition) {
   obj = std::unique_ptr<A>(new B(args));
} else {
   obj = std::unique_ptr<A>(new C(args));
}
4
Benjamin Lindley

Oui, elle sera hors de portée si elle est déclarée dans une boucle conditionnelle, etc.

0
boba-feh

Votre alternative sera des pointeurs:

MyObject *obj;
if(cond1)
{
    obj = new MyObject(1, 2, 3);
}
else
{
    obj = new MyObject(4, 5);
}

N'oubliez pas de le supprimer lorsque vous avez terminé ou d'utiliser un pointeur intelligent.

0
Dani