Inheritance from a Template Class [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have a template class,in fsm.h file
and derived class in derivata.h file;
the compiler throws errors:
derivata.h: In constructor ‘deri::deri()’:
derivata.h:46: error: no matching function for call to ‘fsm<pin_steps>::fsm()’
fsm.h:30: note: candidates are: fsm<step_type>::fsm(step_type) [with step_type = pin_steps]
fsm.h:12: note: fsm<pin_steps>::fsm(const fsm<pin_steps>&)
fsm.h:
#ifndef FSM_H_
#define FSM_H_
template<class step_type> class fsm {
protected:
step_type step;
step_type step_old;
step_type step_tmp;
bool step_pulse;
char name[256];
public:
fsm(step_type);
void set_name(char *parent, char *myname);
void test();
virtual void update(){cout << "base\n";};
void show(){cout << step << ' ' << step_tmp << '\n'; };
void init(step_type st_current) {step = st_current;};
//virtual ~fsm();
};
//constructor
template <class step_type> fsm<step_type>::fsm(step_type) {
step = step_old = step_tmp = (step_type)0 ;
step_pulse = false;
}
template <class step_type> void fsm<step_type>::set_name(char *parent, char *myname) {
sprintf(name, "%s.%s", parent, myname);
}
template <class step_type> void fsm<step_type>::test() {
if (step != step_old) {
step_pulse = true;
step_tmp = step_old;
} else step_pulse = false;
step_old = step;
}
#endif /* FSM_H_ */
and a derived class from template class:
#include "fsm.h"
#ifndef DERIVATA_H_
#define DERIVATA_H_
enum taglio_steps {
ST_TAGLIO_CHECK_MOTORE,
ST_TAGLIO_ZERO_MOTORE,
ST_TAGLIO_WAIT_ZERO_MOTORE
};
enum pin_steps {
ST_PIN_BOOT,
ST_PIN_RETURN
};
class deri : public fsm<pin_steps>{
private:
bool cmd_prelevamento_done;
bool cmd_scorrimento_done;
float posizione_pinza_i;
float posizione_pinza_f;
public:
deri(){
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};
void update(){cout << "deri\n";};
// virtual ~deri();
};
#endif /* DERIVATA_H_ */

Your base class doesn't have a non-parameter constructor, but in your derived class you are calling one (it is called automatically).
Change this:
deri(){
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};
To this (pseudocode, I am not sure about correct syntax, I do not use this too often):
deri(): fsm<pin_steps>(ST_PIN_BOOT) {
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};

The base class doesn't have a default constructor which is needed if (in constructor of a derived class) you don't specify which one should be called. If you dont' want fsm to be default-constructible, do this instead:
deri() : fsm(ST_PIN_BOOT) // call fsm::fsm(pin_steps)
{
// ...
}

The compiler error seems pretty clear. You are not calling the fsm<> constructor, and there are no default constructors for fsm. Your options are thus:
Create a default constructor: fsm::fsm() { ... }
Or, more likely in your case: call the constructor in the deri initalization list, like this:
deri() : fsm(step_type_here)
{
cmd_prelevamento_done = false;
cmd_scorrimento_done = false;
posizione_pinza_i = 0;
posizione_pinza_f = 0;
};
I would also recommend putting the other member variable initializations in the initializer list too.

That code is too big but i think you need a default constructor in the base class. Looks like Something like this
public:
fsm(); //added
fsm(step_type);
void set_name(char *parent, char *myname);
void test();
virtual void update(){cout << "base\n";};
void show(){cout << step << ' ' << step_tmp << '\n'; };
void init(step_type st_current) {step = st_current;};
//virtual ~fsm();

Related

c++ read access violation with extended classes [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
As the title says when I run my program, visual studio, give me that error. The class that produce that error is the following:
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene& scene) : scene(scene) {}
void Start() { scene.Start(); }
void EventHandler(SDL_Event ev) { scene.EventHandler(ev); }
void Update() { scene.Update(); }
void Draw(SDL_Renderer* renderer) { scene.Draw(renderer); }
};
The popup appears after } at the end of the initialization of the Start void.
Another code that can interact with these classes is the following:
void GameManager::regScene(UsesScene scene) {
if (display != NULL) {
UsesScene* ptr = &scene;
UsesScene** pptr = &ptr;
display = *pptr;
}
else
{
UsesScene* ptr = &scene;
UsesScene** pptr = &ptr;
buffer = *pptr;
}
}
the display & buffer are declared as
class GameManager
{
private:
SDL_Window* window;
SDL_Renderer* renderer;
UsesScene* display;
UsesScene* buffer;
bool isRunning;
bool reStart;
};
and for access to the display or buffer's parameter I use the following syntax:
display->Start();
and the last thing that has to do with this class is this part of code:
TestScene tScene;
UsesScene testScene(tScene);
this->regScene(testScene);
Test Scene simply extends BaseScene:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start() { std::cout << "BasceScene::Start()" << std::endl; };
virtual void EventHandler(SDL_Event event) {};
virtual void Update() {};
virtual void Draw(SDL_Renderer* renderer) {};
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
How I can solve this?
ps:
some code that doesn't interfere with the Display and Buffer wasn't reported, if you need: free to ask
So, after a few hours of coding, thanks to Remy Lebeau, I've finally resolved this issue.
First I've changed the regScene() method and now looks like this:
void GameManager::regScene(UsersScene *scene) {
if (SceneManager::_display == NULL)
_display = scene;
else
_buffer = scene;
}
And then I pass the scene like this:
TestScene tScene;
UsersScene testScene(tScene);
sManager->regScene(&testScene);
Thanks to all.

How to use polymorphism to execute command on objects, which have no common base class?

I am receiveing commands through json, which I insert in to a pipe. For this reason thye must have the same base class.
The pipe is read by a pipe handler, some commands are consumed by the pipe handler, others have to be passed down to a device, which is a member of the pipe handler. I could simply do this:
class Command{};
class HandlerCommand : public Command {
void execute(Handler* h);
};
class DeviceCommand : public Command {
void execute(Device* d);
};
Command* c = pipe.receive();
if (const auto hc = dynamic_cast<const HandlerCommand*>(c)) { hc.execute( **handlerptr** ); }
else if (const auto dc = dynamic_cast<const DeviceCommand*>(c)) { dc.execute( **deviceptr** );}
Device and pipehandler should not have the same base, since they have no common methods, fields, they are conceptually different.
Is there a way to avoid using dynamic cast here. I was thinking maybe there is some neat design pattern for this, but couldn`t quit come up with a better solution.
EDIT: did not derive DeviceCommand and HandlerCommand from command, fixed this.
You cannot use polymorphism of two things which have nothing in common. You will need the same base class/interface: in your case Command. As mentioned above your base class requires a pure virtual function that must be implemented by the derived classes. I will utilize a Command * clone()const prototype, which could be very useful later on. Please introduce a virtual destructor of your base class, otherwise, to track down this memory error could be a pain in the ass. Note, regarding your dynamic_cast the member function execute, must be const. You may try this:
#include <iostream>
#include <vector>
class Handler
{
public:
Handler(){}
};
class Device
{
public:
Device(){}
};
enum class CommandType{Handler,Devise};
class Command
{
public:
virtual ~Command(){}
virtual Command*clone()const = 0;
virtual CommandType getType()const = 0;
};
class HandlerCommand : public Command {
public:
HandlerCommand():Command(){}
void execute(Handler* h) const
{
std::cout << __FUNCTION__<<"\n";
}
HandlerCommand*clone()const { return new HandlerCommand(*this); }
CommandType getType()const { return CommandType::Handler; }
};
class DeviceCommand : public Command{
public:
DeviceCommand():Command(){}
void execute(Device* d)const
{
std::cout << __FUNCTION__<<"\n";
}
DeviceCommand*clone()const { return new DeviceCommand(*this); }
CommandType getType()const { return CommandType::Devise; }
};
int main()
{
Device dev;
Handler handler;
std::vector<Command*> pipe{ new HandlerCommand(), new DeviceCommand() };
while (!pipe.empty())
{
Command* c = pipe.back();
if (c->getType() == CommandType::Handler) { static_cast<const HandlerCommand*>(c)->execute(&handler); }
else if (c->getType() == CommandType::Devise ) { static_cast<const DeviceCommand*>(c)->execute(&dev); }
delete c;
pipe.pop_back();
}
std::cin.get();
}
outputs:
DeviceCommand::execute
HandlerCommand::execute
Version 2.0 using std::variant. You will need at least C++17 to compile this. Note, a single pipe container can exclusively comprise one of the mentioned classes within the variant. So there is no casting anymore, but you will need two pipes. Because of that, I introduced a time stamp variable.
#include <iostream>
#include <vector>
#include <variant>
class Handler
{
public:
Handler() {}
};
class Device
{
public:
Device() {}
};
class HandlerCommand {
int ts;
public:
HandlerCommand(int _ts):ts(_ts) {}
void execute(Handler* h) const
{
std::cout << ts << ": "<< __FUNCTION__ << "\n";
}
int timeStamp()const { return ts; }
};
class DeviceCommand {
int ts;
public:
DeviceCommand(int _ts) :ts(_ts) {}
void execute(Device* d)const
{
std::cout << ts << ": " << __FUNCTION__ << "\n";
}
int timeStamp()const { return ts; }
};
using Command = std::variant<HandlerCommand, DeviceCommand>;
int main()
{
Device dev;
Handler handler;
std::vector<Command> hcPipe{HandlerCommand(2),HandlerCommand(5)};
std::vector<Command> dcPipe{DeviceCommand(1),DeviceCommand(4)};
Command single = DeviceCommand(0);
if (single.index() == 0)
{
std::get<HandlerCommand>(single).execute(&handler);
}
else
{
std::get<DeviceCommand>(single).execute(&dev);
}
while (!hcPipe.empty() || !dcPipe.empty())
{
if (!hcPipe.empty() && (dcPipe.empty() || std::get<HandlerCommand>(hcPipe.front()).timeStamp() < std::get<DeviceCommand>(dcPipe.front()).timeStamp()))
{
std::get<HandlerCommand>(hcPipe.front()).execute(&handler);
hcPipe.erase(hcPipe.begin());
}
else
{
std::get<DeviceCommand>(dcPipe.front()).execute(&dev);
dcPipe.erase(dcPipe.begin());
}
}
std::cin.get();
}
outputs:
0: DeviceCommand::execute
1: DeviceCommand::execute
2: HandlerCommand::execute
4: DeviceCommand::execute
5: HandlerCommand::execute

Override virtual function with more parameters

I have an array of happy people.
Each happy person has a virtual function called updateHappiness() which is used to update their happiness attribute.
Each person likes their own thing.
Rain lovers are happy persons who really like hearing the sound of the rain and it increases their happiness level. They inherit from the happy person class.
As a consequence, they need to know when it is raining while updating their happiness by overloading the updateHappiness() function with updateHappiness(bool isRaining) as in this post : overload virtual function with different parameters in c++, however, this is a problem because there are many kinds of people and we would like to update them all by calling the same function for every person.
We could have the parameter stored inside of the person class and pass it in the class constructor as in this post : Override number of parameters of pure virtual functions however rain is not a constant state and we would have to call a function updateRainState(bool isRaining) which would cause the same problem as before.
We could pass the parameter bool isRaining to every person even though they don't care about the rain but it would also be a problem because some people like the rain, some people like seeing the daylight, some people like it when their friends are happy... so it would add many useless parameters and it seems like a waste.
Finally, the best solution I could think of is to have a static function in the weather class to get the rain state without passing it as a parameter but it would look like a global variable and some people say that it is really bad!
What would you do to solve this problem ?
Here is an example code of what the classes are like :
class HappyPerson
{
public:
HappyPerson(): m_happinness(0) {}
virtual void updateHappinness() { m_happinness++; }
protected:
int m_happinness;
};
class Weather
{
public:
static int isRaining() { return raining; }
private:
static bool raining;
};
bool Weather::raining(0);
class RainLover : public HappyPerson
{
public:
RainLover() : HappyPerson() {}
void updateHappinness() { m_happinness++; if (Weather::isRaining()) m_happinness++; }
};
int main()
{
std::vector<HappyPerson*> happyPeople;
happyPeople.push_back(new RainLover);
// ... add many other persons
std::vector<HappyPerson*>::iterator it;
for (it = happyPeople.begin(); it != happyPeople.end(); it++)
{
(*it)->updateHappinness();
}
}
You should consider taking a completely different approach - use event callbacks instead.
When something in particular changes, only interested people are affected, so you should not waste time and effect trying to passing around the change to everyone else.
If a person's happiness depends on the Weather, then have the person register for Weather change events.
If a person's happiness depends on another person's happiness, then have the person register for the other person's happiness change events.
And so on.
For example:
class HappyPerson;
class HappinessChangeListener
{
public:
void happinessChanged(HappyPerson *person, bool isHappier) = 0;
};
class HappyPerson
{
public:
HappyPerson();
virtual ~HappyPerson() {}
void updateHappiness(int amount);
void registerHappinessChangeListener(HappinessChangeListener *listener);
void unregisterHappinessChangeListener(HappinessChangeListener *listener);
);
protected:
int m_happinness;
std::vector<HappinessChangeListener*> happinessChangeListeners;
void happinessChanged(bool isHappier);
};
...
HappyPerson::HappyPerson()
: m_happinness(0)
{
}
void HappyPerson::updateHappiness(int amount)
{
if (amount != 0)
{
m_happinness += amount;
happinessChanged(amount > 0);
}
}
void HappyPerson::registerHappinessChangeListener(HappinessChangeListener *listener)
{
happinessChangeListeners.push_back(listener);
}
void HappyPerson::unregisterHappinessChangeListener(HappinessChangeListener *listener)
{
std::vector<HappinessChangeListener*>::iterator i = std::find(happinessChangeListeners.begin(), happinessChangeListeners.end(), listener);
if (i != happinessChangeListeners.end())
happinessChangeListeners.erase(i);
}
void HappyPerson::happinessChanged(bool isHappier)
{
for(std::vector<HappinessChangeListener*>::iterator i = happinessChangeListeners.begin(); i != happinessChangeListeners.end(); ++i)
i->happinessChanged(this, isHappier);
}
class Weather;
class WeatherChangeListener
{
public:
void weatherChanged(Weather *weather) = 0;
};
class Weather
{
public:
Weather();
void rainStarted();
void rainStopped();
bool isRaining();
void registerWeatherChangeListener(WeatherChangeListener *listener);
void unregisterWeatherChangeListener(WeatherChangeListener *listener);
protected:
bool m_raining;
std::vector<WeatherChangeListener*> weatherChangeListeners;
void weatherChanged();
};
...
Weather::Weather()
: m_raining(false)
{
}
void Weather::rainStarted()
{
if (!m_rRaining)
{
m_rRaining = true;
weatherChanged();
}
}
void Weather::rainStopped()
{
if (m_rRaining)
{
m_rRaining = false;
weatherChanged();
}
}
bool Weather::isRaining()
{
return m_raining;
}
void Weather::registerWeatherChangeListener(WeatherChangeListener *listener)
{
weatherChangeListeners.push_back(listener);
}
void Weather::unregisterWeatherChangeListener(WeatherChangeListener *listener)
{
std::vector<WeatherChangeListener*>::iterator i = std::find(weatherChangeListeners.begin(), weatherChangeListeners.end(), listener);
if (i != weatherChangeListeners.end())
weatherChangeListeners.erase(i);
}
void Weather::weatherChanged()
{
for(std::vector<WeatherChangeListener*>::iterator i = weatherChangeListeners.begin(); i != weatherChangeListeners.end(); ++i)
i->weatherChanged(this);
}
class RainLover : public HappyPerson, public WeatherChangeListener
{
public:
RainLover(std::shared_ptr<Weather> &weather);
~RainLover();
void weatherChanged(Weather *weather);
protected:
std::shared_ptr<Weather> m_weather;
};
...
RainLover::RainLover(std::shared_ptr<Weather> &weather)
: HappyPerson(), m_weather(weather)
{
m_weather->registerWeatherChangeListener(this);
}
RainLover::~RainLover()
{
m_weather->unregisterWeatherChangeListener(this);
}
void RainLover::weatherChanged(Weather *weather)
{
updateHappiness(weather->isRaining() ? 1 : -1);
}
class HappyLover : public HappyPerson, public HappinessChangeListener
{
public:
HappyLover(std::shared_ptr<HappyPerson> &person);
~HappyLover();
void happinessChanged(HappyPerson *person, bool isHappier);
protected:
std::shared_ptr<HappyPerson> m_person;
};
...
HappyLover::HappyLover(std::shared_ptr<HappyPerson> &person)
: HappyPerson(), m_person(person)
{
m_person->registerHappinessChangeListener(this);
}
HappyLover::~HappyLover()
{
m_person->unregisterHappinessChangeListener(this);
}
void HappyLover::happinessChanged(HappyPerson *person, bool isHappier)
{
updateHappiness(isHappier ? 1 : -1);
}
int main()
{
std::shared_ptr<Weather> weather(new Weather);
std::vector<std::shared_ptr<HappyPerson>> happyPeople;
happyPeople.push_back(std::shared_ptr<HappyPerson>(new RainLover(weather)));
// or: happyPeople.push_back(std::make_shared<RainLover>(weather));
happyPeople.push_back(std::shared_ptr<HappyPerson>(new HappyLover(happyPeople[0])));
// or: happyPeople.push_back(std::make_shared_ptr<HappyLover>(happyPeople[0]));
// ... add many other persons
weather->rainStarted();
...
weather->rainStopped();
...
}

Pointer to function-member

I have a FreeRTOS function xTaskCreate. Simplified declaration looks like
typedef void (*TaskFunction_t)( void* );
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void*params );
And there are two classes:
class Super {
virtual void task(void*params) = 0;
};
class Derived1 : public Super {
virtual void task(void*params){ while(1){ blinkLed(1); delay_ms(333); } }
};
class Derived2 : public Super { ... ;}
In function init() I select one of derived classes and create its instance. Then want to create task
void init(){
Super *obj = condition ? new Derived1 : new Derived2;
xTaskCreate( obj->task ); // WRONG.
}
Upd. Add missed void*params in Simplified declaration of xTaskCreate.
TaskFunction_t is just a pointer to a function - so it can't take a pointer to a member function. Only a pointer to normal function. Or a static member function. Or a lambda with no capture. It's that last one that we'll take advantage of.
One of the arguments you removed from your simplified declaration is the context:
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
unsigned short usStackDepth,
void *pvParameters, // <== this one!
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
);
You provide the Super* in the parameters and provide a lambda that knows what to do with it. Altogether:
void init(){
Super *obj = condition ? new Derived1 : new Derived2;
xTaskCreate([](void* o){ static_cast<Super*>(o)->task(); },
..., // other args here
obj,
... // more args
);
}
Note that task() should take no arguments. The void*is the context that we're converting to a Super*.
After several experiements of my own with answers here I prefered this simpler method giving Object oriented function calls to RTOS tasks.
//These are not full declaration of class IModule which is fully abstarct so //object that are IModule* are always inherited.
protected:
virtual int InitModule() = 0;
virtual bool PreLoop() = 0;
virtual bool DoLoop() = 0;
virtual bool PostLoop() = 0;
virtual bool DoShutdown() = 0;
//Return if this module implementation requires an RTOS task looping.
virtual bool isFreeRTOSTaskRequired() = 0;
private:
TaskHandle_t *moduleLoopTaskHandle;
bool CreateRTOSTask();
static void TaskStart(void* taskStartParameters);
void TaskLoop();
//END OF PARTIAL decleration
bool IModule::CreateRTOSTask()
{
xTaskCreate(IModule::TaskStart, "NAME", 2048, this, tskNO_AFFINITY, moduleLoopTaskHandle);
return true;
}
void IModule::TaskStart(void *taskStartParameters)
{
IModule *moduleObject = (IModule *)taskStartParameters;
moduleObject->TaskLoop();
}
void IModule::TaskLoop()
{
//TODO Buraya ölçüm koyalım ve bir değişkene yazalım
while (true)
{
ESP_LOGD("IModule::TaskLoop", "%s", "I am alive!");
if (!PreLoop())
{
}
if (!DoLoop())
{
}
if (!PostLoop())
{
}
}
vTaskDelete(NULL);
}
UPDATED: See below.
As explained better than I can here, you might get away with this. Hard to tell from your question if it will cover all of your requirements.
typedef void (Super::*TaskFunction_t)( void* );
Further Reading
UPDATE:
I fleshed out your example, and the results and code are below:
XXXXX:~/scratch/member_function_pointer$ bin/provemeright
Condition false
virtual void Derived2::task(void*)
XXXXX:~/scratch/member_function_pointer$ bin/provemeright foo
Condition true because of argument foo
virtual void Derived1::task(void*)
code (all one cpp file, bad form, but proves syntax):
#include <iostream>
class Super;
typedef void (Super::*TaskFunction_t)(void*);
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void* params);
bool condition = false;
class Super {
public: virtual void task(void* params) = 0;
};
class Derived1 : public Super {
public: virtual void task(void* params) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if(params) // Necessary to prevent unused parameter warning
std::cout << "Not Null" << std::endl;
};
};
class Derived2 : public Super {
public: virtual void task(void* params) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
if(params) // Necessary to prevent unused parameter warning
std::cout << "Not Null" << std::endl;
};
};
void init(){
Super *obj = condition ? (Super*)new Derived1 : (Super*)new Derived2;
xTaskCreate( &Super::task , obj);
}
int main(int argc, char **argv)
{
if(argc > 1)
{
std::cout << "Condition true because of argument " << argv[1] << std::endl;
condition = true;
} else {
std::cout << "Condition false" << std::endl;
}
init();
return 0;
}
unsigned xTaskCreate( TaskFunction_t pxTaskCode, void* params)
{
Super *obj = (Super*) params;
(obj->*pxTaskCode)(NULL);
return 0;
}
If you're concerned that the syntax is &Super::task instead of &obj->task, then you're misunderstanding how virtual functions work. (It turns out that the &obj->task syntax forbidden by ISO C++, but gcc says it's permissive, so you shouldn't but could force it to compile, and get exactly the same result)
The information about which virtual version of a function to call 'lives' in the object, not the type system. (Could probably phrase that better, open to suggestions, but I think it gets the general point across) It is impossible to call a member function without an object, so in order to make use of the function pointer, you'll have to have an object to 'call it on'. It is the type of that object which will determine which virtual function gets called. So the code above should achieve whatever you're going for, unless of course, this is a round-about way to determine the type of the object pointed to by obj, in which case, it's an awfully convoluted way of going about it.
Further Reading specifically in "Kerrek SB"s answer.

How to call a function from any class by a pointer to it? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm building an engine. I need to create a Timer class which will call a function by a pointer from a separate class. For example:
class MyTimer {
public:
void setTimeoutFunction( _pointer_, unsigned short timeoutMs ) {
// here we need to have a opportunity to store a _pointer_ to a function
}
void tickTimer() {
...
// here I need to call a function by a pointer
...
}
};
// Main class:
class MyAnyClass {
public:
void start() {
MyTimer myTimer;
myTimer.setTimeoutFunction( startThisFunc, 1500 ); // 1500ms = 1.5s
while ( true ) {
myTimer.tickTimer();
}
}
void startThisFunc() { ... }
}
In summation, how do you store a pointer to a function which belongs to some class and call that function by a pointer?
For your requirements, I might recommend making the timer a class template:
template <typename T>
struct MyTimer
{
using FuncPtr = void (T::*)();
MyTimer(FuncPtr ptr, T * obj, unsigned int timeout_ms)
: ptr_(ptr), obj_(obj), timeout_ms_(timeout_ms) {}
void tickTimer()
{
(obj_->*ptr_)();
}
FuncPtr ptr_;
T * obj_;
unsigned int timeout_ms_;
};
Usage:
struct MyAnyClass
{
void start()
{
MyTimer<MyAnyClass> myTimer(&MyAnyClass::startThisFunc, this, 1500);
while (true) { myTimer.tickTimer(); }
}
void startThisFunc() { /* ... */ }
};
In C++11 you can use std::function. A good guide on using it is here: http://en.cppreference.com/w/cpp/utility/functional/function
I created a new code snippet only containing the case you want.
#include <stdio.h>
#include <functional>
#include <iostream>
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
};
int main()
{
// store a call to a member function
std::function<void(const Foo&, int)> f_add_display = &Foo::print_add;
const Foo foo(314159);
f_add_display(foo, 1);
return 0;
}