if语句中变量的作用域

32

我有一个类没有默认的构造函数或赋值运算符,因此根据另一个函数的结果,在if/else语句中声明和初始化该类。但是稍后它会说它超出了范围,即使条件语句的两个路径都会创建一个实例。

考虑以下示例(使用int只是为了说明这一点):

#include <iostream>

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

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

在条件语句中声明的变量是否会在条件语句结束时超出作用域?如果没有默认构造函数,但构造函数的参数取决于某些条件,应该如何处理这种情况?

编辑

鉴于给出的答案,情况更加复杂,因此可能需要改变方法。有一个抽象基类A和两个派生自A的类B和C。如何处理像这样的情况:

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

改变方法?因为A是抽象的,我不能只声明A* obj并使用new来创建适当的类型。


你的继承是虚拟的还是静态的? - Daniel
虚拟的,我想。如果你是指class A有一个虚函数(C++不是我的强项,我主要使用Fortran),那就是这样。 - tpg2114
你实际上可以声明一个指向抽象类的指针 - 我已经编辑了我的答案。 - Luchian Grigore
4个回答

32

"在条件语句中声明的变量是否在条件结束后就超出了作用域?"

是的 - 本地变量的作用域仅限于封闭括号内:

{
   int x; //scope begins

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

在您的情况下,假设您有类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 );

编辑:

是的,你可以:

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

编辑:

看起来你正在寻找工厂模式(搜索一下):

 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;
    }
 };

1
在这种情况下,内存是否被重新分配??变量作用域在封闭的{}括号结束后。 - kaushalpranav

5

在条件语句中声明的变量会在条件语句结束时超出作用域吗?

是的。

处理没有默认构造函数但构造函数参数取决于某些条件的情况的正确方法是什么?

编写一个返回值的函数,从中复制。

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

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

编辑:

由于A是抽象的,我无法仅仅声明A * obj并使用new创建适当的类型。

你的意思是什么?这正是动态类型的工作原理。不过我不会使用裸指针,而是会使用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));
}

这个答案是否认了第一个答案的观点?(关于在条件语句中声明的变量是否会在该条件语句结束时超出其作用域) - LazerSharks
1
@Gnuey:不是的。我不确定Luchian回答“不”是针对哪个问题。也许他在阅读问题和编写答案之间混淆了措辞。但完整的语句以及随后的代码片段都明确支持我的答案。 - Benjamin Lindley

0

你的另一种选择将是指针:

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

记得在使用完后删除它,或者使用智能指针。


-1

如果在条件语句、循环等中声明变量,它将超出范围。变量的类型是否会根据条件语句而改变?


所以有两种情况。有时无论条件如何,它都是相同类型,有时根据条件不同而是不同类型。这两种情况的方法会如何变化? - tpg2114
我已经看到它如何解决第一个情况(相同类型)。它如何处理基于条件声明不同类型的可能性? - tpg2114

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接