3

it might be strange what i'm trying to see and i will try to clarify as much as possible. I'm using gcc 4.8 on ubuntu 14.04 and C++11.

What i want trying to do is:

  • make a class A
  • make a function in that class A which gets as argument
  • a pointer to a class member of the same class
  • make a new class B which inherits from A
  • make a new method of class B
  • give a pointer to that method of class B to a method of parentclass A as argument

    class A{
        typedef void(A::*METHOD);        
    
        void executeMethod(METHOD arg){};
    }
    
    class B : A{
    
        void sampleMethod(){};
    
        void childMethod(){              
    
          this->executeMethod(&B::sampleMethod); //<== error
        }
    }
    

However this brings me the following error in codeblocks:

error: no matching function to call for 'B::executeMethod(void B::*)'

Is there any way around this? Is there anything else i need to do to make it clear to you, what i'm trying to accomplish?

philsegeler
  • 163
  • 1
  • 1
  • 9

4 Answers4

2

The problem is that sampleMethod isn't a member of A, it's a member of B and can't convert to a void(A::*).

Did you consider using virtual methods perhaps?

Mark B
  • 95,107
  • 10
  • 109
  • 188
2
typedef void(A::*METHOD);        

defines METHOD to be a pointer of type void* to a member variable of A, not a pointer to a member function of A.

You need:

typedef void (A::*METHOD)();        

Even with that change, you can't use a member function of B to pass as an argument where METHOD is expected.

You can make the function that you want to pass a virtual member function of A and use it.

class A {
   protected:
      typedef void(A::*METHOD)();        

      void executeMethod(METHOD arg){};

   public:
      virtual void sampleMethod() = 0;
};

class B : public A {

   virtual void sampleMethod(){};

   void childMethod(){              

      this->executeMethod(&A::sampleMethod);
   }
};
R Sahu
  • 204,454
  • 14
  • 159
  • 270
2

You cannot directly call child method from a base class, but you can use template:

class A {
public:
    template<class T>
    void executeMethod( void (T::*method)() )
    {
        (static_cast<T *>( this )->*method)();
    }
};

class B : public A {
public:
    void sampleMethod() {}
    void childMethod() { executeMethod( &B::sampleMethod ); }
};

But more flexible solution would be to use std::function and std::bind as then you can pass methods which signature does not match.

class A {
public:
    typedef std::function<void()> Method;

    void executeMethod( const Method &method )
    {
        method();
    }
};

class B : public A {
public:
    void sampleMethod1() {}
    void sampleMethod2( int param ) {}

    void childMethod1() { executeMethod( std::bind( &B::sampleMethod1, this ); }
    void childMethod2() { executeMethod( std::bind( &B::sampleMethod2, this, 123 ); }
};
Slava
  • 43,454
  • 1
  • 47
  • 90
1

To make a callable object bound to a member function you should use std::bind. This will create a forwarding wrapper which will call sampleMethod with some of its parameters pre specified. In this case, the "this" parameter will be bound.

std::bind(&B::sampleMethod, this);

Wayne Tanner
  • 1,346
  • 11
  • 18
  • First of all OP does not need a function pointer, he asks a pointer to method. Second `std::bind()` will not make a function pointer. – Slava Feb 17 '15 at 18:38
  • Agreed. My terminology was very loose. I'll edit to correct the wording. – Wayne Tanner Feb 17 '15 at 18:41