Search code examples
c++methodsinitializationfunction-pointerspointer-to-member

Runtime class method replacement during initialisation


Say I have a class which contains a method speak() which will print something to the terminal. What exactly it will print out is determined by an initialisation boolean, if true, it will print "Foo", if false, it will print "Bar". The value of the boolean value is determined at runtime.

One way to implement this would be to add an if statement in the speak() function which would then call either the foo() or bar() method. However, if this class method was called frequently, then the if switch and the additional function call could be avoided by instead replacing the speak() function by either the foo() or bar() function at class initialisation. Is there a way to achieve this functionality using, perhaps using function points?

class MyClass
{
  public:
    MyClass (const bool select)
    {
        if (select)
        {
            // Make speak() use foo();
        }
        else
        {
            // Make speak() use bar();
        }
    }

    speak() const;

  private:
    foo() const { std::cout << "Foo\n"; }
    bar() const { std::cout << "Bar\n"; }
}

It seems like this kind of behaviour would be beneficial, and therefor I assume there's some way of achieving it. However, I haven't had any luck in finding how to do this, mainly because I'm not sure exactly what to google.

Thanks for your help and advice.


Solution

  • It seems like this kind of behaviour would be beneficial, and therefor I assume there's some way of achieving it.

    Yes, it is possible using a member function pointer.

    1. Declare a member variable that is a member function pointer.

        void (MyClass::*speaker)() const;
      
    2. Initialize it appropriately in the constructor.

      MyClass (const bool select)
      {
         if (select)
         {
            speaker = &MyClass::foo;
         }
         else
         {
            speaker = &MyClass::bar;
         }
      }
      
    3. Use it in speak.

      void speak() const
      {
         (this->*speaker)();
      }
      

    Read more about member function pointers at http://en.cppreference.com/w/cpp/language/pointer.

    Here's a working example:

    #include <iostream>
    
    class MyClass
    {
       public:
    
          MyClass (const bool select)
          {
             if (select)
             {
                speaker = &MyClass::foo;
             }
             else
             {
                speaker = &MyClass::bar;
             }
          }
    
          void speak() const
          {
             (this->*speaker)();
          }
    
          void (MyClass::*speaker)() const;
    
       private:
          void foo() const { std::cout << "Foo\n"; }
          void bar() const { std::cout << "Bar\n"; }
    };
    
    int main()
    {
       MyClass m1(true);
       MyClass m2(false);
    
       m1.speak();
       m2.speak();
    }
    

    and its output:

    Foo
    Bar