array of pointers to class methods

A

Anonymoose

Hello,
Hope someone can tell me how to do this - I'm an old 'C' hack so
sometimes I get stuck in old-think...this is one of those times...

I've got a bunch of methods in a class that I want to be able to
lookup and call from an array. In 'c' I'd just do something like:

struct thingie {
char *name;
void (*ptrtofunc)();
} listofthingies[] = {
{ "func1", func1 },
{ "func2", func2 }
};

where func1 and func1 are functions that return void that I would usually
call via something like (for example):

(listofthingies[0].func1)();

Here, the equivalent I have is (abbreviated):

struct functable {
CString name;
void (CMyApp::*wscfunc)();
} functable [] = {
{ "send", &CMyApp::func1 },
{ "wsasend", &CMyApp::func2 },
};



But,
(functable[0].wscfunc)();

just results in "term does not evaluate to a function". None of my
reference books help, in this specific case.

So, two questions here: 1. What is the quick way to resolve this (ie: can
I reference my methods this way?), and 2. What is the better C++ way to
accomplish the same thing?
 
A

Anonymoose

Hello,
Hope someone can tell me how to do this - I'm an old 'C' hack
so
sometimes I get stuck in old-think...this is one of those times...

I've got a bunch of methods in a class that I want to be able
to
lookup and call from an array. In 'c' I'd just do something like:

struct thingie {
char *name;
void (*ptrtofunc)();
} listofthingies[] = {
{ "func1", func1 },
{ "func2", func2 }
};

where func1 and func1 are functions that return void that I would
usually call via something like (for example):

(listofthingies[0].func1)();

Correction...I meant:

(listofthingies[0].ptrtofunc)();
 
T

TT \(Tom Tempelaere\)

Anonymoose said:
Hello,
Hope someone can tell me how to do this - I'm an old 'C' hack so
sometimes I get stuck in old-think...this is one of those times...

I've got a bunch of methods in a class that I want to be able to
lookup and call from an array. In 'c' I'd just do something like:

struct thingie {
char *name;
void (*ptrtofunc)();
} listofthingies[] = {
{ "func1", func1 },
{ "func2", func2 }
};

where func1 and func1 are functions that return void that I would usually
call via something like (for example):

(listofthingies[0].func1)();

Here, the equivalent I have is (abbreviated):

struct functable {
CString name;
void (CMyApp::*wscfunc)();
} functable [] = {
{ "send", &CMyApp::func1 },
{ "wsasend", &CMyApp::func2 },
};



But,
(functable[0].wscfunc)();

You need an object to call a member function on. In your case, an object of
type CMyApp.

Tom.
 
A

Anonymoose

Anonymoose said:
Hello,
Hope someone can tell me how to do this - I'm an old 'C' hack so
sometimes I get stuck in old-think...this is one of those times...

I've got a bunch of methods in a class that I want to be able to
lookup and call from an array. In 'c' I'd just do something like:

struct thingie {
char *name;
void (*ptrtofunc)();
} listofthingies[] = {
{ "func1", func1 },
{ "func2", func2 }
};

where func1 and func1 are functions that return void that I would
usually call via something like (for example):

(listofthingies[0].func1)();

Here, the equivalent I have is (abbreviated):

struct functable {
CString name;
void (CMyApp::*wscfunc)();
} functable [] = {
{ "send", &CMyApp::func1 },
{ "wsasend", &CMyApp::func2 },
};



But,
(functable[0].wscfunc)();

You need an object to call a member function on. In your case, an
object of type CMyApp.

Tom.

Thanks - I found the "other" fix too - to declare the methods as static.
 
T

TT \(Tom Tempelaere\)

Anonymoose said:
Anonymoose said:
Hello,
Hope someone can tell me how to do this - I'm an old 'C' hack so
sometimes I get stuck in old-think...this is one of those times...

I've got a bunch of methods in a class that I want to be able to
lookup and call from an array. In 'c' I'd just do something like:

struct thingie {
char *name;
void (*ptrtofunc)();
} listofthingies[] = {
{ "func1", func1 },
{ "func2", func2 }
};

where func1 and func1 are functions that return void that I would
usually call via something like (for example):

(listofthingies[0].func1)();

Here, the equivalent I have is (abbreviated):

struct functable {
CString name;
void (CMyApp::*wscfunc)();
} functable [] = {
{ "send", &CMyApp::func1 },
{ "wsasend", &CMyApp::func2 },
};



But,
(functable[0].wscfunc)();

You need an object to call a member function on. In your case, an
object of type CMyApp.

Tom.

Thanks - I found the "other" fix too - to declare the methods as static.

That is indeed the 'other' fix, because you didn't really need an object to
operate on. This is how you could do it for member methods (just an
example).

struct my_class {
int i;
my_class(int i_) : i(i_) {}
int increment() { return ++i; }
int decrement() { return --i; }
};

struct callable {
typedef int (my_class::* callable_fn)();

my_class mc;
callable_fn the_func;

callable(const my_class& mc_, callable_fn the_func_)
: mc(mc_), the_func(the_func_)
{}
int operator()() {
return (mc.*the_func)();
}
};

int main() {
callable cl[] = {
callable( my_class(5), &my_class::increment ),
callable( my_class(7), &my_class::decrement )
};
for(int i=0; i != (sizeof(cl)/sizeof(*cl)); ++i)
std::cout << cl() << std::endl;

std::swap( cl[0].the_func, cl[1].the_func );

while( cl[0].mc.i != 0 )
for(int i=0; i != (sizeof(cl)/sizeof(*cl)); ++i)
cl();
}

Tom.
 
M

Mihajlo Cvetanovic

Anonymoose said:
Here, the equivalent I have is (abbreviated):

struct functable {
CString name;
void (CMyApp::*wscfunc)();
} functable [] = {
{ "send", &CMyApp::func1 },
{ "wsasend", &CMyApp::func2 },
};

But,
(functable[0].wscfunc)();

You need an object to call a member function on. In your case, an
object of type CMyApp.

Thanks - I found the "other" fix too - to declare the methods as static.

Static methods are less useful than non-static (there's no inheritance
and you can't have more than one behaviorally different set of
methods). I believe there's a more elegant solution for your design,
but more background data is needed. What should this class do?

In the worst case I would make a class with only one virtual public
function, with only one parameter LPCTSTR. This function would do its
thing based on this parameter (whether it's "send", "wsasend", or
something else). Anyway, how is it possible you don't need any
parameters for your functions?
 
H

Hendrik Schober

Mihajlo Cvetanovic said:
[...] I believe there's a more elegant solution for your design,
but more background data is needed. What should this class do?

It looks like Anonymoose is trying
to re-invent virtual functions. When
I saw the posting I wondered why one
wouldn't use them for this task.

Schobi

--
(e-mail address removed) is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
 
A

Anonymoose

Mihajlo Cvetanovic said:
[...] I believe there's a more elegant solution for your design,
but more background data is needed. What should this class do?

It looks like Anonymoose is trying
to re-invent virtual functions. When
I saw the posting I wondered why one
wouldn't use them for this task.

Cause he doesn't understand them that well (yet). The task, is reading
lines of input, parsing them, and calling one of a set of functions with
the parsed arguments, based on what the arguments are.
 
H

Hendrik Schober

Anonymoose said:
Mihajlo Cvetanovic said:
[...] I believe there's a more elegant solution for your design,
but more background data is needed. What should this class do?

It looks like Anonymoose is trying
to re-invent virtual functions. When
I saw the posting I wondered why one
wouldn't use them for this task.

Cause he doesn't understand them that well (yet).

They do pretty much exactly what you are
trying to do. Only that compilers rarely
ever make kistakes with this. :)
The task, is reading
lines of input, parsing them, and calling one of a set of functions with
the parsed arguments, based on what the arguments are.


Without investing too much time. This is
what I would start with:

struct functor {
virtual void operator()() const = 0;
};

typedef std::map<std::string,functor*> func_map;

Schobi

--
(e-mail address removed) is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
 
A

Anonymoose

Anonymoose said:
[...] I believe there's a more elegant solution for your design,
but more background data is needed. What should this class do?

It looks like Anonymoose is trying
to re-invent virtual functions. When
I saw the posting I wondered why one
wouldn't use them for this task.

Cause he doesn't understand them that well (yet).

They do pretty much exactly what you are
trying to do. Only that compilers rarely
ever make kistakes with this. :)
The task, is reading
lines of input, parsing them, and calling one of a set of functions with
the parsed arguments, based on what the arguments are.


Without investing too much time. This is
what I would start with:

struct functor {
virtual void operator()() const = 0;
};

typedef std::map<std::string,functor*> func_map;

Thanks - that hurts my head, but I'll dig into it.
 
H

Hendrik Schober

Anonymoose said:
[...]
Without investing too much time. This is
what I would start with:

struct functor {
virtual void operator()() const = 0;
};

typedef std::map<std::string,functor*> func_map;

Thanks - that hurts my head, but I'll dig into it.


To me fiddling with those nasty function
signatures make my brain spin. :)

Using functors instead of functions has
the great advantage that they can carry
around state:

struct my_functor : public functor {
my_functor(const std::string& str) : str_(str) {}
virtual void operator()() const
{
// ca use 'str_' here
}
std::string& str_;
};

void f(const functor& func);

void g()
{
f( my_functor("sn") );
f( my_functor("afu") );
}

With real function( pointer)s you need
global variables or -- worse -- 'void*'
in to do this.

When you do this with a map like the
above: There is the issue of life time
for those functors. If you create them
using 'new', you should use some smart
pointer ins the map, not a raw pointer.
In the boost lib (www.boost.org) is one
that fits your needs. (You must not use
'std::auto_ptr<>' for STL containers.)

Schobi

--
(e-mail address removed) is never read
I'm Schobi at suespammers dot org

"Sometimes compilers are so much more reasonable than people."
Scott Meyers
 

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

Top