Chris Condy
Chris Condy

Reputation: 636

Function member pointers

I have something similar to

Base.h

#ifndef BASE_H
#define BASE_H

class Base
{
virtual Base* createNew() = 0;
}

#endif

D.h

#ifndef D_H
#define D_H

#include "Base.h"

class D : public Base
{
virtual Base* createNew();
}

#endif

D.cpp

#include "D.h"
Base* D:createNew()
{
return new D();
}

main.cpp

typedef Base* (Base::*FP)(void);

#include "D.h"

void create(FP pointer)
{
//empty for now
}

int main()
{
create(&D::createNew); //This doesnt work =s?

}

I am extremely confused why this doesn't work can anybody give me some advice on what I should be doing????

Ps. Sorry if the code doesnt run I put it there for example sakes just to show you what I was doing

Upvotes: 0

Views: 116

Answers (3)

iammilind
iammilind

Reputation: 70096

After fixing following trivial compiler errors in your code,

  1. Missing ; after class body
  2. Changing D:createNew to D::createNew
  3. Making D::createNew in public specifier

Your code doesn't compile at, create(&D::createNew). Because it's not convertible. The error message is clear:

error: cannot convert ‘Base* (D::*)()’ to ‘FP {aka Base* (Base::*)()}’ 

Edit: One way is to use template evaluation, if you decide to do it at compile time.

template<typename ReturnType, typename Class>
void create(ReturnType (Class::*pointer)())
{
}

Call it as:

create<Base*, D>(&D::createNew);

Upvotes: 1

Kaz
Kaz

Reputation: 58667

try:

 create(&Base::createNew);

After all, create wants a Base::* pointer to member, not a D::*.

I don't think there is covariance across inheritance lines for pointers-to-member; Base::* type pointer-to-member is incompatible with a D::* type pointer to member.

However, you can still call the D virtual function through the Base pointer to member on a D object. A D really is a kind of Base, and so you can do dinst->*pmemb where pmemb is a &Base::createNew`.

Also ...

Your D::createNew can return D *. This "covariance" in the return type of a virtual function is allowed in C++. It is still the same virtual function which overrides the one in the Base which returns Base *. When you're calling D::createNew directly, you might sometimes appreciate getting a D * pointer so you can work with the D stuff.

Upvotes: 1

Joachim Isaksson
Joachim Isaksson

Reputation: 181077

There are numerous syntax problems in your code;

  • Base::createNew() is private and virtual.
  • Neither class declaration has a terminating ;.
  • D:createNew() should be D::createNew(). ...

I think what you're referring to though is that taking a member function pointer and passing it to a method won't work.

The problem is that you're taking a method that can only be called with a D and trying to pass it as a pointer to a function that can take a Base that is not necessarily a D. The reverse would work, (ie passing Base::createNew() to a function taking a D::createNew() since Base::createNew() always exists in a D, not the other way around)

Upvotes: 2

Related Questions