Re: Better way to call member function using function pointer?
On 17 Nov, 20:05, Ganesh Pagade <ganesh.pag...@gmail.com> wrote:
Hi,
Following is isolated code reproducing the issue I encountered while
using function pointers:
//////////////////////////////////////////////
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Sample
{
public:
Sample()
{
funPtrs["fun1"] = &Sample::fun1;
funPtrs["fun2"] = &Sample::fun2;
funPtrs["fun3"] = &Sample::fun3;
This is the wrong way to go about initialising funPtrs (appologies if
this is just because you've simplified for your post).
Should probably be done by the constructor of a static object of class
SampleInit in Sample.cxx with the implementation of Sample() taken out
of line. That way it will be done once before any Sample object is
constructed.
(definition of funPtrs must come before the init because the order of
construction of statics in a single compilation unit is well defined)
}
void process()
{
string str[] = { "fun1", "fun2", "fun3" };
// Method 1 - Compilation error.
for (int i = 0; i < 3; ++i)
{
// VS 2005 gives me error as:
// error C2064: term does not evaluate to a function taking 1
arguments
funPtrs[str[i]]("hi");
Pointer to a member of what object????
Yes you are calling it in a member function but you could just as
easily call it on another object - The compiler cannot assume that
just because you are in a member of "this" that you want to call the
function on "this" (see below).
}
// Method 2 - Works fine.
for (int i = 0; i < 3; ++i)
{
ptr = funPtrs[str[i]];
(this->*ptr)("hello");
but could just as easily be
(that->*ptr)("hello");
which is why 1 doesn't work.
NB there is no reason to have ptr and certainly no reason to make it a
member:
(this->*funPtrs[str[i]])("hello");
}
}
private:
void fun1(string str)
{
str = "fun1";
cout << str << endl;
}
void fun2(string str)
{
str = "fun2";
cout << str << endl;
}
void fun3(string str)
{
str = "fun3";
cout << str << endl;
}
private:
static map<string, void (Sample::*)(string)> funPtrs;
void (Sample::*ptr)(string);
Not needed
};
map<string, void (Sample::*)(string)> Sample::funPtrs;
int main()
{
Sample s;
s.process();
return 0;}
//////////////////////////////////////////////
To my understanding Method 1 gives error because function is called
using pointer which is not a member of Sample, due to which "this"
cannot be passed to the member function as argument. Hence the
mentioned error.
Adding a pointer as member variable specifically to make the function
calls, works fine (Method 2). I was wondering if this is the only way
to do it or there exist a better method/design to achieve this.
See above
Regards,
Ganesh
P.S. It's often helpful for this sort of mapping code to make the
strings static members of the class:
class Sample { ...
public: static const string FUN1;
That way you can maybe save a little space or time and sometimes avoid
errors, at least in test programs - The strings have to be created
somewhere and they have to be "known" so they might as well be in the
interface.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]