user1854865
user1854865

Reputation: 23

Storing a derived pointer to method

I want to create a class, that has pointer to one of its methods as attribute. Then there should be a method, that is used to set this pointer.

class A {
    private:
        void (A::*curr_f)();
    public:

        void set(void (A::*f)()) {
            curr_f = f;
        }
};

Problems start when I try to create inherited class and set the pointer to one of its methods.

class B : A {
    public:
        void main() {
            set(&B::new_function);
        };
        void new_function() {};
};

Errors I'm getting are quite straightforward, but still, I have no idea how to solve this.

error: no matching function for call to ‘B::set(void (B::*)())’
note: candidate is:
note: void A::set(void (A::*)())
note: no known conversion for argument 1 from ‘void (B::*)()’ to ‘void (A::*)()’

Upvotes: 2

Views: 95

Answers (2)

Nik
Nik

Reputation: 1334

You can have the code like this:


   #include <iostream>

using namespace std;

template<class T>
class A {
  protected:
    void (T::*curr_f)();
  public:

    virtual void set(void (T::*f)()) {
      curr_f = f;
      cout<<"Set in A"<<endl;
      T obj;
      (obj.*curr_f)();
    }

    virtual void new_function() {cout<<"in A"<<endl;};

};


class B :public A<B> {

  public:
    void func() {
      set(&B::new_function);
    };
    void new_function() {cout<<"in B"<<endl;};

};

int main()
{

  B obj;
  obj.func();

}

Upvotes: 0

masoud
masoud

Reputation: 56519

You can't. A has not method new_function and you're lying to the compiler. You have three ways

1.

Move new_function to A and pass A::new_function (as virtual is preferred).

class A
{
    void (A::*curr_f)();
public:
    void set(void (A::*f)())
    {
        curr_f = f;
    }
    virtual void new_function() {};
};

class B : A
{
public:
    void main()
    {
        set(&A::new_function);
    };
    void new_function() {};
};

 

2.

Forward B declaration and store B::* in the A:

class B;

class A
{
    void (B::*curr_f)();
public:
    void set(void (B::*f)())
    {
        curr_f = f;
    }
};

class B : A
{
public:
    void main()
    {
        set(&B::new_function);
    }
    void new_function() {}
};

 

3.

You can try template based ways, like the curiously recurring template pattern (CRTP).

template <typename D>
class A
{
    void (D::*curr_f)();
public:
    void set(void (D::*f)())
    {
        curr_f = f;
    }
};

class B : public A<B>
{
public:
    void main()
    {
        set(&B::new_function);
    }
    void new_function() {}
};

Upvotes: 6

Related Questions