Search code examples
c++polymorphismc++17

How to pass a virtual function as an argument in C++?


I am trying to write this code below:

// Type your code here, or load an example.
#include <iostream>

class A
{
public:
    virtual void virFunc1(int a) = 0;
    virtual void virFunc2(int a) = 0;
    void func1(int a)
    {
        onTempFunc(this->virFunc1, a);
    }
    void func2(int a)
    {
        onTempFunc(this->virFunc2, a);
    }
private:
    template <typename ImplFunc, typename... Args>
    void onTempFunc(ImplFunc impl_func, Args&&... args)
    {
        impl_func(args...);
    }
};

class B : public A
{
public:
    void virFunc1(int a) override
    {
        std::cout << "virFunc1: " << a << std::endl;
    }

    void virFunc2(int a) override
    {
        std::cout << "virFunc2: " << b << std::endl;
    }
};

int main()
{
    auto* A = new B();
    A->func1(2);
    A->func2(3);
}

But the compilation is failing in godbolt: https://godbolt.org/z/dq4szorq7 with the error: error: invalid use of non-static member function 'virtual void'. Basically I want to pass a virtual method to a function template along with its arguments. The function template will call that virtual method inside it. The different virtual methods can have different function signatures, that is why I have made onTempFunc a function template. Is there a way in C++ to achieve this?


Solution

  • The correct syntax for passing virFunc1 and virFunc2 as arguments would be to write &A::virFunc1 and &A::virFunc2 respectively as shown below.

    Additionally, for calling/using the passed member function pointer we can use ->* as shown below:

    class A
    {
    public:
        virtual void virFunc1(int a) = 0;
        virtual void virFunc2(int a) = 0;
        void func1(int a)
        {
    //-----------------vvvvvvvvvvvv-------->changed this
            onTempFunc(&A::virFunc1, a);
        }
        void func2(int a)
        {
    //-----------------vvvvvvvvvvvv------->changed this 
            onTempFunc(&A::virFunc2, a);
        }
    private:
        template <typename ImplFunc, typename... Args>
        void onTempFunc(ImplFunc impl_func, Args&&... args)
        {
    //-------vvvvvvvvvvvvvvvvvvvvvvvvvv------> used ->* for member function pointer
            (this->*impl_func)(args...);
        }
    };
    

    Working demo.

    Also refer to Passing functions as parameters in C++