Reputation: 23
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
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
Reputation: 56519
You can't. A
has not method new_function
and you're lying to the compiler. You have three ways
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() {};
};
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() {}
};
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