Lengdon
Lengdon

Reputation: 79

How to pass function of one class as argument of another function of another class

I have created a class Base which has a function addSuccessor() that takes address of function as argument and stores it in successor. How do I pass a function of another object in addSuccessor(). Here is my program. I think my main() has some mistake.

#include <iostream>
#include<vector>
using namespace std;
class Base{
public:
    void (*successor)()=NULL;
    void addSuccessor ( void (*f)() )
    {
        successor=f;
    }
    void start()
    {
        cout<<"In Class"<<endl;
        if(!successor==NULL)
            successor();
        else
            cout<<"No Successor"<<endl;
    }
};
class Second{
    public:
    void foo()
    {
        cout<<"Successor";
    }
};

int main()
{
    Base obj;
    Second obj2;

    obj.addSuccessor(&obj2.foo());
    obj.start();

}

Upvotes: 2

Views: 134

Answers (2)

Soumya Kanti
Soumya Kanti

Reputation: 1479

As a complement to the discussion above (based on @L.F.'s answer):

#include <functional>
#include <iostream>
#include <utility>

class Base {
    std::function<int(int)> successor;
public:
    template <typename F>
    void add_successor(F&& f)
    {
        successor = std::forward<F>(f);
    }
    void start()
    {
        if (successor) {
            auto z = std::invoke(successor, 100);
            std::cout << "Output = " << z << "\n";
        } else {
            std::cout << "No Successor\n";
        }
    }
};

class Second {
public:
    int foo(int x)
    {
        auto y = x + x;
        std::cout << "Successor\n";
        return y;
    }
};

int main()
{
    Base obj;
    Second obj2;

    obj.add_successor([&](int x)->int { return obj2.foo(x); });
    obj.start();
}

Upvotes: 1

L. F.
L. F.

Reputation: 20639

Function pointers are very limited. Use a std::function (defined in header <functional>) instead, which can store any invocable object in a type-erased manner, and provide a template member function to set the functor in which perfect forwarding is used to forward the provided functor to successor: (std::forward is defined in header <utility>)

class Base {
    std::function<void()> successor;
public:
    template <typename F>
    void add_successor(F&& f)
    {
        successor = std::forward<F>(f);
    }
    void start()
    {
        if (successor) {
            successor();
        } else {
            std::cout << "No Successor\n";
        }
    }
};

Then, you can pass a lambda expression to add_successor:

obj.add_successor([&]{ obj2.foo(); });

(live demo)

Upvotes: 3

Related Questions