Author: Ian Osgood
Date: 09:54:52 10/30/03
Go up one level in this thread
On October 29, 2003 at 12:41:36, Michel Langeveld wrote:
>>Hi Michel,
>>
>>I guess forEachGame is a static class function.
>>Then you have to use explicite class specifiers in your typedef:
>>
>>typedef void (PGNtoScreen::*on_game_function_type)(char *moves);
>>
>>Gerd
>
>Hi Gerd,
>
>Thanks for looking.
>
>It's actually a static class function.
Well, no. A static class function would be declared "static void parse(...);"
Normal class methods include a pointer to the object as a hidden parameter, but
static methods don't. Static methods don't have access to non-static methods
and members.
> I think the problem is that the compiler
>doesn't know what object to use for calling this function. I made a complete
>code that shows the same problem. Still puzzled.
>
>#include <iostream>
>#include <stdlib.h>
>
>using namespace std;
>
>#define MAXBUF_SIZE 1000
>
>//typedef void (*line_event_type)(char *line);
>typedef void (PGNtoScreen::*line_event_type)(char *line);
>
>class PGNParse
>{
>public:
> PGNParse()
> {
> }
>
> void parse(char *strTextFile, line_event_type lineEvent)
> {
> char line[MAXBUF_SIZE];
>
> FILE *f = fopen(strTextFile, "r");
> while (!feof(f))
> {
> if (fgets(line, MAXBUF_SIZE, f) == NULL) continue;
>
> lineEvent(line);
> }
> }
>};
>
>class PGNtoScreen
>{
>public:
> PGNtoScreen()
> {
> lines = 0;
> }
>
> void PGNtoScreen::forEachLine(char *strLine)
> {
> cout << strLine;
> lines++;
> }
>
> void PGNtoScreen::doit(char *strFileName)
> {
> PGNParse p;
>
> p.parse(strFileName, forEachLine); //gives error C2664
>
> cout << "Number of lines printed: " << lines << endl;
> }
>
>private:
> int lines;
>};
>
>void main()
>{
> PGNtoScreen o;
> o.doit("docc2003.pgn");
>}
There are several ways to pass object callbacks to object methods.
1. Class inheritance. Your object accesses the callback by inheriting from the
class which implements it. You can avoid parameter passing this way, but you
lose flexibility (you must derive other classes to use other callbacks).
class Callback { void forEachLine() { ... }; };
class Obj2 : public Callback {
void parse () { forEachLine(); }
};
class Obj {
void doit() { Obj2 callee; callee.parse(); }
};
2. Pass the whole object. The method called knows the interface of the passed
in class (or one of its inherited classes). This can be useful if you need more
than one callback method accessible. You can also derive other classes from
Callback to implement different behavior.
class Callback { virtual void forEachLine() = 0; }; // interface
definition
class Obj2 {
void parse( Callback *callback ) { callback->forEachLine(); }
};
class Obj : public Callback {
virtual void forEachLine() { ... };
void doit() { Obj2 callee; callee.parse(this); }
};
3. Pass a static callback method plus a pointer to the object itself. This way
is often used if the function you are calling is plain C and outside your
control (such as a system call).
class Obj {
void forEachLine();
static void callback(void* context) { ((Obj *)context)->forEachLine(); }
void doit() { syscall( callback, this ); }
};
Ian
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.