Call child class methods in parent class

  • Thread starter Martin Herbert Dietze
  • Start date
M

Martin Herbert Dietze

Hello,

I would like to implement a callback mechanism in which a
child class registers some methods with particular signatures
which would then be called in a parent class method.

In half-code this should in the end look like this:

In the child class:

| int ChildClass::fooHandler(int a, char b)
| {
| //[...]
| }
|
| int ChildClass::barHandler(int a, char b)
| {
| //[...]
| }
|
|
| void ChildClass::init (void)
| {
| registerMethod ("foo", &fooHandler);
| registerMethod ("bar", &barHandler);
| }

In the parent class:

| int ParentClass::runHandler (const char *tag, int a, char b)
| {
| HandlerType *handler = findMethod (tag);
| return (*handler) (a, b);
| }

In the real life problem, the code in the parent class is of
course much more complex. In the existing implementation this
is all done in the child classes, so that we got a lot of
unnecessary redundance in the code.


The problem is that because different child classes would
define different numbers of such methods (and thus also of
different names) using abstract methods does not seem to help
here.

Has anybody managed to get something like this running?

Cheers,

Martin
 
K

Karl Heinz Buchegger

Martin said:
[snip]

Has anybody managed to get something like this running?

What is your particular problem *exactly*.
Do you get error messages from the compiler or do
you have other problems?
What you posted seems like the beginning of a road which
leeds to a solution.
 
V

Victor Bazarov

Martin said:
I would like to implement a callback mechanism in which a
child class registers some methods with particular signatures
which would then be called in a parent class method.

What is by your definition a "child" and what's a "parent"?
Examples: the child class derives from the parent, or the parent
class object contains a child object (or a pointer), or ???

The reason I ask is that C++ does not have terms "child" or "parent"
and everybody seems to have their own definition of those terms. I
would like to know yours before attempting to give advice.
In half-code this should in the end look like this:

In the child class:

| int ChildClass::fooHandler(int a, char b)
| {
| //[...]
| }
|
| int ChildClass::barHandler(int a, char b)
| {
| //[...]
| }
|
|
| void ChildClass::init (void)
| {
| registerMethod ("foo", &fooHandler);
| registerMethod ("bar", &barHandler);
| }

In the parent class:

| int ParentClass::runHandler (const char *tag, int a, char b)
| {
| HandlerType *handler = findMethod (tag);
| return (*handler) (a, b);

So, how is 'HandlerType' defined? It seems that it's a pointer to
a function. That suggests that 'fooHandler' and 'barHandler' are
static member functions of 'ChildClass'. If not, please elaborate.
| }

In the real life problem, the code in the parent class is of
course much more complex. In the existing implementation this
is all done in the child classes, so that we got a lot of
unnecessary redundance in the code.

I don't know what that all means. Is it really relevant?
The problem is that because different child classes would
define different numbers of such methods (and thus also of
different names) using abstract methods does not seem to help
here.

What abstract methods? Whose abstract methods?
Has anybody managed to get something like this running?

I am fairly certain that many folks have done something similar.
However, you didn't specify enough to understand what to give as
an example.

V
 
M

Martin Herbert Dietze

Victor Bazarov said:
What is by your definition a "child" and what's a "parent"?
Examples: the child class derives from the parent, or the parent
class object contains a child object (or a pointer), or ???

No, I am talking about inheritance. `ChildClass' is derived from
`ParentClass'.
So, how is 'HandlerType' defined? It seems that it's a pointer to
a function. That suggests that 'fooHandler' and 'barHandler' are
static member functions of 'ChildClass'. If not, please elaborate.

The snippet above tries to explain what I want in the end.
Thus, I did not define `HandlerType' in this context. Having a
proper definition for `HandlerType' so that it can be used to
call methods of a derived class in a base class, would actually
be a huge step towards solving my problem.
I don't know what that all means. Is it really relevant?

Only for people asking the "this does not look like too much
redundancy, why do you want to go through all this?" question.
Strictly speaking it is not.
What abstract methods? Whose abstract methods?

E.g. `virtual void method() = 0;' in the base class. Since the
derived classes would have to implement it the method can be
used in base class code.
I am fairly certain that many folks have done something similar.
However, you didn't specify enough to understand what to give as
an example.

The problem is about generating different tree structures in
specific parsers which are all derived from a generic parser.
Experience has shown that many of the specific parsers look
pretty similar, so that I hope to put more intelligence into
the base class.
I would thus like to register handler methods for specific
attributes in the specific parsers which would then be called
in the generic one. Does that make more sense to you?

Cheers,

Martin
 
V

Victor Bazarov

Martin said:
[...]
The problem is about generating different tree structures in
specific parsers which are all derived from a generic parser.

OK. I can be wrong, but AFAIK, it has been solved in many parsers.
Experience has shown that many of the specific parsers look
pretty similar, so that I hope to put more intelligence into
the base class.

Intelligence. OK, I'll bite. What intelligence?
I would thus like to register handler methods for specific
attributes in the specific parsers which would then be called
in the generic one. Does that make more sense to you?

Again, this is too generic. Are you talking about XML processing?
If yes, look at SAX. If you're talking about something not
necessarily limited to processing XML, then what? If you don't
have a model yet, how can we help? Ask maybe in comp.object. If
you do have a model, please describe it. We can then try to come
up with the C++ code for it.

At this junction I can only see the requirement to register some
kind of callback so that it is invoked if some condition is met.
There are plenty of "register -- call if encountered" schemes out
there, choose any you like. Even MFC has one.

V
 
A

Abecedarian

Martin said:
No, I am talking about inheritance. `ChildClass' is derived from
`ParentClass'.


The snippet above tries to explain what I want in the end.
Thus, I did not define `HandlerType' in this context. Having a
proper definition for `HandlerType' so that it can be used to
call methods of a derived class in a base class, would actually
be a huge step towards solving my problem.

Maybe you can use this library:
http://www.codeproject.com/cpp/FastDelegate.asp

A.
 
J

Jonathan Mcdougall

"Martin Herbert Dietze" <[email protected]> a écrit dans le message
de
Hello,

I would like to implement a callback mechanism in which a
child class registers some methods with particular signatures
which would then be called in a parent class method.

In half-code this should in the end look like this:

Have a look at Loki's Functor class.

class Parent
{
public:
typedef Loki::Functor<int, TYPELIST_2(int, char)> handler;
handler foo;


void trigger_foo(int i, char c)
{
if (foo)
{
foo(i, c);
}
}
};


class Child : public Parent
{
public:
Child()
{
foo = handler(this, &Child::test);
}

int test(int i, char c)
{

}
};

Jonathan
 
M

Martin Herbert Dietze

Victor Bazarov said:
Again, this is too generic. Are you talking about XML processing?
If yes, look at SAX. If you're talking about something not
necessarily limited to processing XML, then what? If you don't
have a model yet, how can we help? Ask maybe in comp.object. If
you do have a model, please describe it. We can then try to come
up with the C++ code for it.

Look, this is the kind of discussion I wanted to avoid, this is
not about the C++ programming language. There may be third
party software that can help me build my application, but this
is not what I am asking for. The question boils down to this:

How can I implement and register callback functions in a
derived class that can then be called in its base class?
At this junction I can only see the requirement to register some
kind of callback so that it is invoked if some condition is met.

Of course this is the way to go. However, a non-static member
function carries its object's type information as part of its
signature. Therefore calling a callback member function of a
derived class raises a technical problem - how can it be done
in C++?

Cheers,

Martin
 
M

Martin Herbert Dietze

Jonathan Mcdougall said:
Have a look at Loki's Functor class.

This looks very good indeed. Having just read a lot about
member-function callbacks in C++ (also thanks to the
documentation coming with FastDelegate and Boost) it seems
to me that this involves a lot of magic. At least good to
know that it can be made to work :)

Cheers,

Martin
 
V

Victor Bazarov

Martin said:
[...]
Of course this is the way to go. However, a non-static member
function carries its object's type information as part of its
signature. Therefore calling a callback member function of a
derived class raises a technical problem - how can it be done
in C++?

In the following example the classes are related. They don't
need to be.

----------------------------------------------
#include <string>
#include <map>

class A;
class B {
typedef void (A::*pothermember)(int,double);
typedef std::map<std::string,pothermember> mymap;
mymap mp;
public:
B() {}
void registercallback(std::string const& s, pothermember);
void callback(std::string const& s, A*, int, double);
};

void B::registercallback(std::string const& s, pothermember p)
{
mp = p;
}

void B::callback(std::string const& s, A* pa, int i, double d)
{
pothermember p = 0;
mymap::iterator it = mp.find(s);
if (it != mp.end())
p = it->second;
if (p && pa)
(pa->*p)(i, d);
}

#include <iostream>

class A : public B {
void foo(int i, double d) {
std::cout << "A::foo(" << i << ' ' << d << ")\n";
}
public:
A() { this->registercallback("foo", &A::foo); }
};

int main()
{
A a;
a.callback("foo", &a, 42, 3.1415926);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,023
Latest member
websitedesig25

Latest Threads

Top