I have a stack of function pointers (all of void type & with no parameters). I am having difficulty finding out how I then call/execute a function that is in the stack?
If you look at the simple example below everthing compiles & works except for the last line
typedef class InstructionScreen;
typedef void (InstructionScreen::*MemberFuncPtr)();
stack <MemberFuncPtr> instructionStep; // This is how I declare it. Works
instructionStep.push( &InstructionScreen::step1 ); // This is how I add the member function step(). Works
(*instructionStep.top())(); // How do I call the function now? This doesn't work
This is the whole code I am attempting to get to compile:
class InstructionScreen
{
public:
InstructionScreen()
{
instructionStep.push( &InstructionScreen::step1 );
instructionStep.push( &InstructionScreen::step2 );
// add timer to call run instructions each 10 seconds
}
void step1()
{
}
void step2()
{
}
void runInstructions()
{
if ( !instructionStep.empty() )
{
*(instructionStep.top())();
instructionStep.pop();
}
// else kill timer
}
private:
stack <MemberFuncPtr> instructionStep;
};
You need an instance to call a member function. Try this:
InstructionScreen screen;
MemberFuncPtr step = instructionStep.top();
(screen.*step)();
To run a function in the stack from within another member function, you can use:
MemberFuncPtr step = instructionStep.top();
(this->*step)();
Related
I'm new in C++. I'm trying to do clickable button with OpenGL. I work for add callback function for each button for 2 days, I tried many methods I found but I can't do this. My below codes are giving memory error. Where is my mistake?
main.h
#include <vector>
class Button {
public:
// Storage Vector
static std::vector<Button> Buttons;
// typedef Function
typedef void (*pointerFunction)();
// Constructor
Button(/*Parameters*/);
// Setting Callback
void setCallBack(void(*function)());
// Callback pointer
pointerFunction callback;
int value{ 4 };
};
main.cpp
#include <iostream>
#include "main.h"
std::vector<Button> Button::Buttons;
Button::Button(/*Parameters*/) {
// ...
Button::Buttons.push_back(*this);
}
void Button::setCallBack(void(*function)()) {
this->callback = function;
this->callback(); // Here is work!
}
void testFunction() {
std::cout << "Test\n";
}
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
int main() {
createMember();
for (Button& button : Button::Buttons) {
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
return 0;
}
Within this function
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
there are two things that are being doing. The first one is creating the local object classMember. The called construcfor pushes a copy of the object inside the vector Buttons. The data member callback of the copy was not initialized.
It is the data member callback of the .local object classMember that was initialized after its copy was pushed on the vector.
Rewrite the function at least like
void createMember() {
Button classMember;
Button::Buttons.back().setCallBack(&testFunction);
}
You should initialize all data members for example using in particular the literal nullptr if a corresponding initializer was not explicitly supplied. In this case you will be able to check whether a data member of a pointer type is equal to nullptr or stores an actual value.
Your createMember function don't work as you expect.
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
Creates a local object that will be destroyed at function exit.
You can do it like this (though I don't think it is a good solution.)
Button & createMember() {
static Button classMember;
classMember.setCallBack(&testFunction);
return classMemeber;
}
A better solution:
std::vector<Button> Button::Buttons;
int main() {
Button b;
for (Button& button : Button::Buttons) {
button.setCallBack(testFunction);
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
return 0;
}
Note that you have to defile Button::Buttons somewhere as it is a static member This was correct in your code, I overlooked it.
And, to add at least a Button, you have to create one to be added to the vector.
Ouput:
Test
4Test
You are calling testFunction twice, at setCallBack and in the loop.
(I've added a newline.)
If as the createMember function name suggest, you want to call that to create each new element, you could pass the function pointer in constructor. If it is trivially copyable like is in your example (no pointers or resource allocation in the class) you can just create the instance and the vector copy will be fine.
Button::Button(pointerFunction f) : callback (f) {
// ...
Button::Buttons.push_back(*this);
}
void createMember() {
Button classMember (testFunction);
}
int main() {
createMember ();
for (Button& button : Button::Buttons) {
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
}
I don't think this is a good design for anything real, though.
Your mistake is that you create a local object, push the copy of it into the vector, put the callback address to the original object, and then destroy the original object. Well, you can put the callback address as the constructor argument, then the copy would have it.
// Constructor
Button(void(*function)(), /*Parameters*/) : callback{function} {
Button::Buttons.push_back(*this);
}
But I would recommend to add a static function to the Button class which is responsible for creation a Button object and returning reference to it. This is also eliminate unnecessary creation/deletion of temporary objects.
#include <iostream>
#include <vector>
class Button {
public:
// Storage Vector
static std::vector<Button> Buttons;
// typedef Function
typedef void (*pointerFunction)();
// Constructor
Button(/*Parameters*/);
// Setting Callback
void setCallBack(void(*function)());
// Callback pointer
pointerFunction callback;
template<class... U>
static Button& createButton(U&&... u) {
return Buttons.emplace_back(std::forward<U>(u)...);
}
int value{ 4 };
};
std::vector<Button> Button::Buttons;
Button::Button(/*Parameters*/) {
// ...
Button::Buttons.push_back(*this);
}
void Button::setCallBack(void(*function)()) {
this->callback = function;
this->callback(); // Here is work!
}
void testFunction() {
std::cout << "Test\n";
}
void createMember() {
auto &classMember = Button::createButton(/**/);
//Button classMember;
classMember.setCallBack(&testFunction);
}
int main() {
createMember();
for (Button& button : Button::Buttons) {
std::cout << button.value;
button.callback();
}
return 0;
}
I'm writing a simple event bus system to get familiar with this model. I have an addEvent function which takes an event name (string) and a function. I'm having trouble establishing my event class.
// Event class to define our event
class Event
{
public:
// function is some function that needs to be executed later
Event(const string eventName, void * function)
{
msgEvent.first = event;
msgEvent.second = function;
}
string getEvent(){
return msgEvent;
}
private:
pair<string, void*> msgEvent;
};
so when I make a call addEvent("open", openFunction), I would like to store this information as part of an Event.
I'm having a hard time understanding how I can store the function and if I'm correctly passing a function in the constructor as a parameter.
You can use function pointers or std::function. void* is for sure not correct. In any case, you need to know what signature your function has. Let's say, your functions do not take any input and do not return. Then, their signature is void()
Then, you can use the following code:
#include<functional>
#include<string>
class Event
{
public:
// function is some function that needs to be executed later
Event(const std::string eventName, std::function<void()> functionName)
{
msgEvent.first = eventName;
msgEvent.second = functionName;
}
std::string getEvent(){
return msgEvent.first;
}
void execute() {
msgEvent.second();
}
private:
std::pair< std::string, std::function<void()> > msgEvent; // why are you using
// std::pair here?
};
Now, you can write
Event myEvent( "open", [](){ /* do something */ } );
myEvent.execute();
My intention is to design event callback model in network communication,the event callback includes "recv,send,accept,shutdown..."
class client
{
public:
template<typename F1>
void bind_recv(F1 && f)
{
// How to save the parameter of bind_recv function in _recv_callback member variable ?
_recv_callback = f;
}
// bind_send
// bind_accept
// bind_shutdown
// ...
protected:
void notify_recv()
{
_recv_callback();
}
// notify_send
// ...
// How to declare the type of these variable ?
F1 _recv_callback;
// F2 _send_callback;
// ...
};
int main()
{
client c;
c.bind_recv([](uint8_t * data, size_t len)
{
});
return(0);
}
I need to save callbacks and call them at the right time, but the parameters of each callback function are different, so how do I save them?
I guess maybe my thinking is wrong, so how can I change the design to meet this requirement?
I am trying to write a program that will execute a function based on a string I fetch from a database.
Basically what I do is:
// Create an enum
enum AFunc{
invalidFunction,
function2,
function3
}
// have a class handling the functions
struct A
{
static AFunc resolveStringToFunction(std::string) {...}
template<int T>
void execute(...)
{
// this may not be called = invalidFunction
}
template<>
void execute<1> (...)
{
// do stuff = function1
}
template<>
void execute<2> (...)
{
// do stuff = function2
}
};
In my application i do this:
A a;
std::string funcString = getFromDatabase (...) // Not really, but this is abstract
const AFunc funcType = A::resolveStringToFunction(funcString);
a.execute<funcType>(...);
The problem here is that the compiler does not accept the dynamic calling of a template function, because (as I understood it) it needs to know which function is called by compile time.
Is there any way around this?
Is there a better solution to this problem? Maybe a design pattern?
namespace afunc // dont pollute global namespace
{
typedef std::function<void(...)> aFunc;
static function1(...)
{
// do stuff
}
static function2(...)
{
// do stuff
}
const std::unordered_map<std::string, aFunc> functions (
{{"function1", &function1},{"function2", &function2}} ); // afunc
And it is called by the following code:
std::string funcString = getFromDatabase (...) // Not really, but this is abstract
afunc::functions.at(funcString)(...) // at because the map is const, so it's even threadsafe
Suppose I have some functions:
void func1 (){
...
}
void func2(){
...
}
int main(){
func1();
//check called functions
return 0;
}
I'd like to check which function was called. Here it is func1. I can make one more special checker-function for this. But is it possible to get the name of the function, which was called from stack frame and how?
I recommend not calling the functions directly, but instead use function objects:
struct func_base
{
virtual const std::string& get_function_name(void) const = 0;
virtual void execute(void) = 0;
void operator() (void)
{
execute();
}
};
This would allow you to retrieve the name of the function that you executed.
By the time the code is compiled, this information is not known anymore. You can use ad hoc solutions, such as return function name from the function itself (use __FUNCTION__ macro to make your life easier). This will be very ugly, of course.