6

I'm attempting to pass a pointer to a function that is defined in one class into another class. After much research, I believe my syntax is correct, but I am still getting compiler errors. Here is some code which demonstrates my issue:

class Base
{
public:
    BaseClass();
    virtual ~BaseClass();
};

class Derived : public Base
{
public:
    // assign strFunction to the function pointer passed in
    Derived(string (*funPtr)(int)) : strFunction(funPtr);
    ~Derived();

private:
    // pointer to the function that is passed in
    string (*strFunction)(int value);
};

class MainClass
{
public:
    MainClass()
    {
        // allocate a new Derived class and pass it a pointer to myFunction
        Base* myClass = new Derived(&MainClass::myFunction);    
    }

    string myFunction(int value)
    {
        // return a string
    }
};

When I try to compile this code, the error I get is

error: no matching function for call to 'Derived::Derived(string (MainClass::*)(int))'

followed by

note: candidates are: Derived::Derived(string (*)(int))

Any idea what I might be doing wrong?

9 Answers 9

8

your syntax is correct for a C style function pointer. Change it to this:

Derived(string (MainClass::*funPtr)(int)) : strFunction(funPtr) {}

and

string (MainClass::*strFunction)(int value);

remember to call strFunction, you will need an instance of a MainClass object. Often I find it useful to use typedefs.

typedef string (MainClass::*func_t)(int);
func_t strFunction;

and

Derived(func_t funPtr) : strFunction(funPtr) {}
Sign up to request clarification or add additional context in comments.

5 Comments

and what about if the classes are decoupled and you cannot specify 'MainClass::*funPtr' ?
Then I would recommend using a generic library like making the parameter a boost::function<std::string()> and passing the function with boost::bind
tx but what about non-boost project? std::function() and std::bind() are only available in C++11 which we dont have.
@fduff: they are actually accessible in tr1 as well. If that is still not an option, I would either recommend updating your toolchain, or asking a more detailed question here on stackoverflow and letting someone come up with an answer more tailored for your specific goals.
you're right, these functions are part of the tr1, which is available under vs2010. I'll take a closer look, tx.
5

You can learn more about the grave wickedness that is C++ member function pointer syntax here.

Comments

4

Yes, the type of &MainClass::myFunction is a pointer-to-member type whereas string(*)(int) is a pointer-to-function type. They are not compatible as you have to use a reference or pointer to a class instance and use the .* or ->* operators to use a pointer-to-member, whereas a pointer to a function is not attached to a class and can be called directly.

Comments

4

You are trying to pass a pointer to a member function of the class MainClass, but the function expects a pointer to an ordinary, ie non-member, function. A good summary is here

The difference is important because member functions have a hidden extra parameter which tells the function which "this" pointer to apply the function to. So the pointer types aren't interchangeable.

Comments

2

Function pointers (that is pointers to unbound functions) and pointers-to-methods (that is pointers to non-static functions bound to a class definition), are different in c++. This is because non-static methods have an implicit this argument which requires that they always be called in the context of a instance of their class.

You're trying to pass a method-pointer to a constructor that takes a function-pointer. Which won't work.

Comments

2

Another syntax issue :


    // assign strFunction to the function pointer passed in
    Derived(string (*funPtr)(int)) : strFunction(funPtr);

replace for :


    // assign strFunction to the function pointer passed in
    Derived(string (*funPtr)(int)) : strFunction(funPtr) {};

Comments

1

You may want to look into using std::tr1::bind and std::tr1::function similar to this (untested) code:

class Derived: public Base
{
  public:
    typedef std::tr1::function<string(int)> StringFunc;

    Derived(StringFunc);

  ...

  private:
    StringFunc strFunction;
}

and in MainClass constructor:

myBase = new Derived(std::tr1::bind(&MainClass::myFunction, *this, _1);

The bind function basically binds the member function to a particular object. Which takes care of the this pointer that is inserted by the compiler.

Comments

0

Object methods have a hidden "this" argument. If you pass the method to another class, what gets filled into the "this" argument? You might be able to do it with static (Class) methods.

Comments

0

As the compiler warning is indicating, member function pointers are completely different from regular function pointers.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.