[C++] A::memberfunction cannot be used without an object
Date
October 1, 2020
Introduction
Last week, I had a mission adding a callback function to the system. At first, I thought that’s quite easy so I had the implementation as below, but it ran into an error…
Class A is a listener that needs to execute a callback function when A specific moment and the callback will be set by class B.
Class B has a functoon cal to be executed and it will register the function to A so that it can be carried out when needed. In cal function, it has to sum the arguments and the value which is calculated by doTrick().
First implementation
Header file:
class A
{
public:
A();
function<int(int, int)> callbackFunc;
void setCB(function<int(int, int)>);
int doCB(int, int);
};
class B{
public:
B(A*);
int doTrick();
static int cal(int, int);
};
Cpp file:
A::A()
{
}
void A::setCB(function<int(int, int)> callback)
{
callbackFunc = callback;
}
int A::doCB(int num1, int num2)
{
return callbackFunc(num1, num2);
}
B::B(A *a)
{
a->setCB(cal);
}
int B::doTrick()
{
// Do a trick here.
return 1;
}
int B::cal(int num1, int num2)
{
doTrick();
return num1 + num2;
}
main.cpp
int main()
{
A a = A();
B b = B(&a);
// At a certain moment, object a would execute the callback.
cout << a.doCB(3,5);
return 0;
}
Error
main.cpp:42:13: error: cannot call member function ‘int B::doTrick()’ without object
doTrick();
Explanation
I believe that we all know what callback is so let’s skip it. As the error shows, we cannot call the member function. But why?
That’s because cal is a static function, it cannot access the B class members and functions. And how could we solve it?
Solution
The great Google always give us the answer.
In my opinion, the cal function needs an instance to access B class’s member functions. Fortunately, We can use std::bind to wrap function so as it can complete registering a callback from a class member.
Solution implementation
Header file:
Please be aware that the cal function is not an static function anymore.
class A
{
public:
A();
function<int(int, int)> callbackFunc;
void setCB(function<int(int, int)>);
int doCB(int, int);
};
class B{
public:
B(A*);
int doTrick();
static int cal(int, int);
};
Cpp file:
A::A()
{
}
void A::setCB(function<int(int, int)> callback)
{
callbackFunc = callback;
}
int A::doCB(int num1, int num2)
{
return callbackFunc(num1, num2);
}
B::B(A *a)
{
// Warp the class menber function as a new one.
auto temp = bind(&B::cal, this, placeholders::_1, placeholders::_2);
a->setCB(temp);
}
int B::doTrick()
{
// Do a trick here.
return 1;
}
int B::cal(int num1, int num2)
{
return doTrick() + num1 + num2;
}
Reference
- https://en.cppreference.com/w/cpp/utility/functional/bind
- https://stackoverflow.com/questions/14189440/c-callback-using-class-member