简体   繁体   中英

Expand scope of a variable initialized in a if/else sequence

I'm writing a piece of code in which I'd like to use a different constructor of a class depending on a condition. So far I've used if and else statements to construct the object, but the instance is then 'trapped' in the brackets and can't be used further in the code.

Here is what it looks like in code:

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

I tried using the static keyword without success so far. Is there a common way of conditionally using different constructors without having to redefine the constructors?

try the following :)

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

Take into account that this code will work even if the class has no default constructor.

Here is a demonstrative example

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

I have gotten the following output

p.x = 1, p.y = 2

What output have you gotten? :)

If you want to use a variable outside of a given scope, it must be declared outside that scope.

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

If you want to do it this way, I suggest defining a move assignment operator if the default will not work for your purposes (or there isn't a default move assignment operator).

Also, the code where you are using my_object may be cleaner if you move the if / else blocks and object construction to a separate function, then do something like:

MyClass my_object = make_object(my_boolean);

Or, if arg1 and arg2 aren't global,

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

If creating an object gets more complicated than what you've asked about here, you may wish to look into the factory pattern .

You can use a smart pointer instead of a direct instance:

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

In contrast to some other solutions proposed here, this will also work for bigger if() {} else if() {} sequences, or switch blocks.


In case you can't use a compiler capable of the latest standard, you can use the good old std::auto_ptr in the exactly same manner.

"I tried using the static keyword without success so far."

Good so! A static variable is certainly not what you want here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM