【问题标题】:Expand scope of a variable initialized in a if/else sequence扩展在 if/else 序列中初始化的变量的范围
【发布时间】:2014-07-08 17:33:21
【问题描述】:

我正在编写一段代码,我想在其中根据条件使用不同的类构造函数。到目前为止,我已经使用 ifelse 语句来构造对象,但实例随后被“困”在括号中,无法在代码中进一步使用。

这是它在代码中的样子:

if (my_boolean){
    MyClass my_object(arg1); //calling a first constructor
}
else {
    MyClass my_object(arg1,arg2); //calling another constructor
}
//more code using my_object

到目前为止,我尝试使用 static 关键字没有成功。有没有一种通用的方法可以有条件地使用不同的构造函数,而不必重新定义构造函数?

【问题讨论】:

标签: c++ scope


【解决方案1】:

尝试以下方法:)

MyClass my_object = my_boolean ? MyClass(arg1) : MyClass(arg1,arg2);

请注意,即使该类没有默认构造函数,此代码也可以工作。

这是一个示范性的例子

#include <iostream> 
#include <cstdlib>
#include <ctime>

int main () 
{
    struct Point
    {
        Point( int x ) : x( x ) {}
        Point( int x, int y ) : x( x ), y( y ) {}
        int x = 0;
        int y = 0;
    };

    std::srand( ( unsigned )std::time( 0 ) );

    Point p = std::rand() % 2 ? Point( 1 ) : Point( 1, 2 );

    std::cout << "p.x = " << p.x << ", p.y = " << p.y << std::endl;  

    return 0; 
}

我得到了以下输出

p.x = 1, p.y = 2

你得到了什么输出? :)

【讨论】:

  • 感谢您的意见,在所有提供的解决方案中,这绝对是实施起来更快,所以我选择了它;)
  • @Learningisamess 请注意,这仅适用于简单的是/否决定。
  • @πάνταῥεῖ:是的,我会记得在更复杂的情况下使用(智能)指针。
  • @πάντα ῥεῖ 我展示了适用于任何复合条件的一般方法。这个想法是您可以定义一个本地对象是某个函数,然后使用复制构造函数或移动构造函数将该对象复制到目标对象中。只需用一些函数调用替换三元运算符。
  • 请注意,这需要一个可访问的复制或移动构造函数。
【解决方案2】:

如果要在给定范围之外使用变量,则必须在该范围之外声明它。

void foo()
{
    MyClass my_object;
    if (my_boolean){
        my_object = MyClass(arg1); //calling a first constructor,
                                   //then copy or move assignment
    }
    else {
        my_object = MyClass(arg1,arg2); //calling another constructor,
                                   //then copy or move assignment
    }
    //more code using my_object
}
//Can no longer access my_object

如果你想这样做,我建议定义一个 move assignment operator 如果默认值不能满足你的目的(或者没有默认的移动赋值运算符)。

此外,如果您将 if/else 块和对象构造移动到单独的函数中,那么您使用 my_object 的代码可能会更简洁,然后执行以下操作:

MyClass my_object = make_object(my_boolean);

或者,如果 arg1arg2 不是全局的,

MyClass my_object = make_object(my_boolean, arg1, arg2);

如果创建对象比您在此处询问的更复杂,您可能希望查看factory pattern

【讨论】:

  • 将它移动到函数中可能有用也可能没用,因此它变成MyClass my_object = obj_init(my_boolean);
  • @MooingDuck 我正在考虑添加它,但我意识到函数的内容与我发布的代码相同,除了函数的返回类型将是 MyClass 并且会有最后是return my_object;;没有足够的差异来证明将答案中的代码加倍。
  • 是的,我不会为它写代码,就一句话。我并不是说函数比您的答案更好,只是 有时(绝对不总是)一个函数可能适用于与此类似的代码。
【解决方案3】:

您可以使用智能指针代替直接实例:

std::unique_ptr<MyClass> my_object;

if (my_boolean) {
     //calling a first constructor
    my_object.reset(new MyClass(arg1));
}
else {
    //calling another constructor
    my_object.reset(new MyClass(arg1,arg2));
}
//more code using my_object

与此处提出的其他一些解决方案相比,这也适用于更大的if() {} else if() {} 序列或switch 块。


如果您不能使用支持最新标准的编译器,您可以以完全相同的方式使用旧的 std::auto_ptr

“到目前为止,我尝试使用 static 关键字没有成功。”

那么好! static 变量肯定不是您想要的。

【讨论】:

  • 为什么不只是复制分配?
  • @0x499602D2 也是一个不错的选择,但我想处理 OP 实际显示的内容。
  • @0x499602D2 THX,已修复。
  • 我只使用my_object.reset(new MyClass(...));。但正如弗拉德的回答所示,不需要动态分配。
  • 请注意:这种智能指针仅适用于 C++11。如果您想要早期 C++ 标准中的智能指针,我建议您使用 boost 库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多