Область применения переменных в операторах if - PullRequest
25 голосов
/ 17 декабря 2011

У меня есть класс, у которого нет конструктора по умолчанию или оператора присваивания, поэтому он объявляется и инициализируется в операторе if / else в зависимости от результата другой функции. Но затем он говорит, что позже он выходит за рамки, хотя оба пути условного создания создадут экземпляр.

Рассмотрим следующий пример (сделано с int только для иллюстрации сути):

#include <iostream>

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

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

Переменные, объявленные в условном выражении, выходят за пределы области действия в конце условного выражения? Как правильно обработать ситуацию, когда нет конструктора по умолчанию, но аргументы для конструктора зависят от определенных условий?

Редактировать

В свете полученных ответов ситуация более сложная, поэтому, возможно, подход придется изменить. Существует абстрактный базовый класс A и два класса B и C, которые являются производными от A. Как бы что-то вроде этого:

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

изменить подход? Поскольку A является абстрактным, я не мог просто объявить A* obj и создать соответствующий тип с помощью new.

Ответы [ 4 ]

24 голосов
/ 17 декабря 2011

"Переменные, объявленные в условном выражении, выходят за пределы области в конце условного выражения?"

Да - область действия локальной переменной находится только в квадратных скобках:

{
   int x; //scope begins

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

В вашем случае, скажем, у вас есть class A.

Если вы не имеете дело с указателями:

A a( condition ? 1 : 2 );

или если вы используете другой прототип конструктора:

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

Если вы создаете экземпляр в куче:

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

или вы можете использовать троичный оператор:

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

EDIT:

Да, вы могли бы:

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

EDIT:

Кажется, вы ищете фабричный шаблон (посмотрите):

 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;
    }
 };
4 голосов
/ 17 декабря 2011

Выходят ли переменные, объявленные в условном выражении, в конец условного выражения?

Да.

Как правильно обращатьсяситуация, когда нет конструктора по умолчанию, но аргументы для конструктора зависят от определенных условий?

Напишите функцию, которая возвращает значение, из которого вы копируете.

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

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

Редактировать:

Поскольку A является абстрактным, я не мог просто объявить A * obj и создать соответствующий тип с новым.

Что делатьты имеешь в виду?Именно так работает динамическая типизация.За исключением того, что я бы не использовал необработанный указатель, я использовал бы 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));
}
0 голосов
/ 17 декабря 2011

Ваша альтернатива будет указателями:

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

Не забудьте удалить его, когда закончите, или используйте умный указатель.

0 голосов
/ 17 декабря 2011

Да, если он объявлен в условном выражении, цикле и т. Д., Он выходит за пределы области видимости. Изменится ли тип переменной в зависимости от условного выражения?

...