I want to define a container in the base class, which contains function obj or anything that can make my purpose happen. These function obj can call derived classes' functions. they all take same parameters.
#include <vector>
#include <functional>
#include <iostream>
class Foo {
Foo() {}
virtual ~Foo(){}
virtual void init()
{ registerCallback(0, &Foo::print_ori ); }
void print_ori(int i) const { std::cout << i << '\n'; }
void registerCallback(int key, ??? cb ) // NOT SURE HOW TO DEFINE THIS
{
callbacks[key] = cb;
}
void runCallbacks(int key, int n)
{
auto i = callbacks.find(key);
if (i != callbacks.end()) {
(*i)(*this, n);
}
}
std::map<int, std::function<void(const Foo&, int) > > callbacks; // obviously, it's wrong. how to fix it?
};
struct Foo2 : public Foo {
Foo2(int num) : Foo(num) {}
virtual void init()
{
Foo::init();
registerCallback(11, &Foo2::print1 );
registerCallback(12, &Foo2::print2 );
}
void print1(int i) const { std::cout << " - Foo2.p1 - " << i << endl; }
void print2(int i) const { std::cout << " - Foo2.p2 - " << i << endl; }
};
int main()
{
Foo* obj = new Foo2();
obj->init();
obj->runCallbacks(12, 456);
}
Here's a way to achieve what your code looks like it's trying to do, without using function pointers:
class Foo {
Foo() {}
virtual ~Foo(){}
void print_ori(int i) const { std::cout << i << '\n'; }
virtual void do_runCallbacks(int v)
{
}
void runCallbacks()
{
print_ori(3)
do_runCallBacks(3);
}
};
struct Foo2 : public Foo {
Foo2(int num) : Foo(num) {}
void do_runcallbacks(int v)
{
print1(v);
print2(v);
}
void print1(int i) const { std::cout << " - Foo2.p1 - " << i << endl; }
void print2(int i) const { std::cout << " - Foo2.p2 - " << i << endl; }
};
int main()
{
Foo* obj = new Foo2();
obj->runCallbacks();
}
Now, there may well be reasons to do this completely differently, but I don't see why you should need both virtual functions and inheritance, AND function objects/function pointers. That seems quite wrong to me ("smells bad")
Edit:
Here's something I came up with, that solves the type of problem you describe after edits of the original question.
#include <iostream>
#include <map>
using namespace std;
class event_interface
{
public:
virtual void action(int n) = 0;
};
class event_manager
{
public:
event_manager(int n) : num(n) {}
void register_event(int key, event_interface *eh)
{
handlers[key] = eh;
}
void callback(int key)
{
auto h = handlers.find(key);
if (h != handlers.end())
{
h->second->action(num);
}
}
private:
map<int, event_interface *> handlers;
int num;
};
class handler1 : public event_interface
{
public:
void action(int n) { cout << "in handler1::action. n=" << n << endl; }
};
class handler2 : public event_interface
{
public:
handler2(int n) : data(n) {}
void action(int n)
{
cout << "in handler2::action. n=" << n
<< " data = " << data << endl;
}
private:
int data;
};
class multihandler
{
private:
class handler3: public event_interface
{
public:
void action(int n) { cout << "in handler3::action. n=" << n << endl; }
};
class handler4: public event_interface
{
public:
handler4(multihandler *m) : mh(m) {}
void action(int n)
{
cout << "in handler4::action. n=" << n
<< " data = " << mh->data << endl;
}
private:
multihandler* mh;
};
public:
multihandler(event_manager& em) : h4(this)
{
em.register_event(62, &h3);
em.register_event(63, &h4);
data = 42;
}
private:
handler3 h3;
handler4 h4;
int data;
};
int main()
{
event_manager mgr(3);
handler1 h1;
handler2 h2(77);
multihandler mh(mgr);
mgr.register_event(12, &h1);
mgr.register_event(13, &h2);
int evts[] = { 12, 63, 62, 13, 18 };
for(auto i : evts)
{
cout << "Event: " << i << endl;
mgr.callback(i);
}
}