Spacey
Spacey

Reputation: 3011

In C++, how to choose to run a specific member function without using if-statements?

I would like to understand if there is an 'elegant' way in which one can choose to run a particular (c++) class member function, based on user input.

For example let us say we have a class such that:

class myClass
{
    int foo;
    myClass(int input) { foo = input;}
    void runMyFunction() 
    { 
        if ( foo == 1) 
        {
            function1();
        }
        else if (foo == 2)
        {
            function2();
        } 
    }


    void function1();
    void function2();
};

What I would like to do, is that if a user specifies input=1 in the constructor, then function1() is called when the runMyFunction() member is called, but if the user had specified input=2 in the constructor, then function2() should be called instead.

My question is, is there a more elegant way to go this without an if statement? The impetus is that I would rather not have the code go through this check over and over again, since I will be using this call in a loop. Is there a more elegant way to 'set' which function is going to be called without if statements in this case? Thanks.

Upvotes: 2

Views: 1898

Answers (4)

Chris Drew
Chris Drew

Reputation: 15334

As Praetorian mentioned in comments you can initialize a member function pointer in the constructor:

class MyClass {
    using FuncPtrType = void (MyClass::*)();
    FuncPtrType myFunction;
  public:
    MyClass(int input) {
        if (input == 1)
          myFunction = &MyClass::function1;
        else 
          myFunction = &MyClass::function2;    
    }

    void runMyFunction() { 
      (this->*myFunction)();
    }
    void function1();
    void function2();
};

If you find the syntax for member function pointers offensive you could use std::function:

class MyClass {
    std::function<void(MyClass*)> myFunction;
  public:
    MyClass(int input) {
        if (input == 1)
          myFunction = &MyClass::function1;
        else 
          myFunction = &MyClass::function2;    
    }

    void runMyFunction() { 
      myFunction(this);
    }
    void function1();
    void function2();
};

Upvotes: 4

Loki Astari
Loki Astari

Reputation: 264471

Yes you can use the command pattern. You just need to set up a array of function method pointers.

std::vector<std::function<void()>>  actionCommand = 
      {[](){}, // Zero based index.
       [this](){this->function1();},
       [this](){this->function2();}
      };

void runMyFunction() 
    { 
        actionCommand[foo]();

        // or 

        actionCommand.at(foo)(); // throws exception if foo is not in
                                 // correct range.
    }

Upvotes: 5

jkras
jkras

Reputation: 324

You can also use a switch statement. There is a simple tutorial to follow here http://www.tutorialspoint.com/cplusplus/cpp_switch_statement.htm

Put simply, I would do something like this

//while user input not equal to x
  // switch (input)
    // case A:
       function 1();
       break;
    // case B:
      .....
    //default:
       //this is the case to use if the input doesn't match any of your predefined cases. You might print a warning here, and reprint your answers.

Good luck

Upvotes: 0

nickn
nickn

Reputation: 184

I don't know if this is elegant or not, but maybe you could have function1 and function2 accept the input, and then the if statements could be placed in function1 and function2, and then execute or just return.

Upvotes: 0

Related Questions