How to invoke the methods of an object selecting them from a table

  • Thread starter Stefano Sabatini
  • Start date
S

Stefano Sabatini

This is my solution for subject:

#include <string>
#include <iostream>

using namespace std;

class DumbThing {
public:
void sayFoo() { cout << "Foo!" << endl; }

static void sayFoo(DumbThing &t) {
t.sayFoo();
}

void sayBar() { cout << "Bar!" << endl; }

static void sayBar(DumbThing &t) {
t.sayBar();
}
};

struct ClassMethod {
string name;
void (*method)(DumbThing &);
};

int main(void) {

struct ClassMethod DumbThingMethods[] = {
{ "sayFoo", &DumbThing::sayFoo },
{ "sayBar", &DumbThing::sayBar }
};

int DumbThingMethodsNum = sizeof(DumbThingMethods) / sizeof(ClassMethod);

DumbThing t;
for (int i=0; i < DumbThingMethodsNum; i++)
DumbThingMethods.method(t);

return 0;
}

The problem with this solution is that I have to create for each
method a corresponding static function, can you contrive a solution
which doesn't require this?

Many thanks in advance for any advice.
 
S

Stefano Sabatini

This is my solution for subject:

#include <string>
#include <iostream>

using namespace std;

class DumbThing {
public:
void sayFoo() { cout << "Foo!" << endl; }

static void sayFoo(DumbThing &t) {
t.sayFoo();
}

void sayBar() { cout << "Bar!" << endl; }

static void sayBar(DumbThing &t) {
t.sayBar();
}
};

struct ClassMethod {
string name;
void (*method)(DumbThing &);
};

int main(void) {

struct ClassMethod DumbThingMethods[] = {
{ "sayFoo", &DumbThing::sayFoo },
{ "sayBar", &DumbThing::sayBar }
};

int DumbThingMethodsNum = sizeof(DumbThingMethods) / sizeof(ClassMethod);

DumbThing t;
for (int i=0; i < DumbThingMethodsNum; i++)
DumbThingMethods.method(t);

return 0;
}

The problem with this solution is that I have to create for each
method a corresponding static function, can you contrive a solution
which doesn't require this?


Sorry for replying to self.

After some thinking I found a satisfying solution, which makes use of
pointers to member and it sounds like this:

#include <string>
#include <iostream>

using namespace std;

class DumbThing {
public:
void sayFoo() { cout << "Foo!" << endl; }
void sayBar() { cout << "Bar!" << endl; }
};

struct ClassMethod {
string name;
void (DumbThing::*method)();
};

int main(void) {

struct ClassMethod DumbThingMethods[] = {
{ "sayFoo", &DumbThing::sayFoo },
{ "sayBar", &DumbThing::sayBar }
};

int DumbThingMethodsNum = sizeof(DumbThingMethods) / sizeof(ClassMethod);

DumbThing t;
for (int i=0; i < DumbThingMethodsNum; i++)
(t.*DumbThingMethods.method)();

return 0;
}

Greetings.
 
O

Ondra Holub

This is my solution for subject:

#include <string>
#include <iostream>

using namespace std;

class DumbThing {
public:
void sayFoo() { cout << "Foo!" << endl; }

static void sayFoo(DumbThing &t) {
t.sayFoo();
}

void sayBar() { cout << "Bar!" << endl; }

static void sayBar(DumbThing &t) {
t.sayBar();
}

};

struct ClassMethod {
string name;
void (*method)(DumbThing &);

};

int main(void) {

struct ClassMethod DumbThingMethods[] = {
{ "sayFoo", &DumbThing::sayFoo },
{ "sayBar", &DumbThing::sayBar }
};

int DumbThingMethodsNum = sizeof(DumbThingMethods) / sizeof(ClassMethod);

DumbThing t;
for (int i=0; i < DumbThingMethodsNum; i++)
DumbThingMethods.method(t);

return 0;

}

The problem with this solution is that I have to create for each
method a corresponding static function, can you contrive a solution
which doesn't require this?

Many thanks in advance for any advice.


To call method, when you have pointer to this method, you need class
instance too. It is not needed for static methods (which are from this
point of view global functions with different visibility), but you
cannot call class method without instance.

For this purpose is used either .* operator or ->* operator. There may
be confusing the syntax, how it is used (due to operator priority).
Use it this way:

DumbThing dt;
DumbThing* dtp = &dt;
void (DumbThing::*method)() = &DumbThing::sayFoo;

(dt.*method)(); // Call method via pointer when you have instance
(dt->*method)(); // Call method via pointer when you have pointer to
instance
 
S

Sam

Stefano said:
This is my solution for subject:

#include <string>
#include <iostream>

using namespace std;

class DumbThing {
public:
void sayFoo() { cout << "Foo!" << endl; }

static void sayFoo(DumbThing &t) {
t.sayFoo();
}

void sayBar() { cout << "Bar!" << endl; }

static void sayBar(DumbThing &t) {
t.sayBar();
}
};

struct ClassMethod {
string name;
void (*method)(DumbThing &);
};

int main(void) {

struct ClassMethod DumbThingMethods[] = {
{ "sayFoo", &DumbThing::sayFoo },
{ "sayBar", &DumbThing::sayBar }
};

int DumbThingMethodsNum = sizeof(DumbThingMethods) / sizeof(ClassMethod);

DumbThing t;
for (int i=0; i < DumbThingMethodsNum; i++)
DumbThingMethods.method(t);

return 0;
}

The problem with this solution is that I have to create for each
method a corresponding static function, can you contrive a solution
which doesn't require this?

Many thanks in advance for any advice.


You want to use class member pointers:

// Declare:

class Foo {

public:
void x();
void y();
};

// Don't use arrays, when you really want a map:

std::map<std::string, void (Foo::*)() > methods;

// Initialize:

methods["x"]= &Foo:x;
methods["y"]= &Foo:y;

// Invoke some method on an object.

void callFoo(Foo *obj, std::string methodname)
{
std::map<std::string, void (Foo::*)() >::iterator p=
methods.find(methodname);

if (p == methods.end())
throw "You are a bozo";

(obj->*(p->second))();
}



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQBHqFJRx9p3GYHlUOIRAjQKAJ9SyKDHF8LQp/dJ9VwY/L9MZ/KcuACeIzwA
ZMvZoGtyo21uvpeIpqAIUoQ=
=CYcU
-----END PGP SIGNATURE-----
 
S

Stefano Sabatini

Stefano said:
This is my solution for subject:

#include <string>
#include <iostream>

using namespace std;

class DumbThing {
public:
void sayFoo() { cout << "Foo!" << endl; }

static void sayFoo(DumbThing &t) {
t.sayFoo();
}

void sayBar() { cout << "Bar!" << endl; }

static void sayBar(DumbThing &t) {
t.sayBar();
}
};

struct ClassMethod {
string name;
void (*method)(DumbThing &);
};

int main(void) {

struct ClassMethod DumbThingMethods[] = {
{ "sayFoo", &DumbThing::sayFoo },
{ "sayBar", &DumbThing::sayBar }
};

int DumbThingMethodsNum = sizeof(DumbThingMethods) / sizeof(ClassMethod);

DumbThing t;
for (int i=0; i < DumbThingMethodsNum; i++)
DumbThingMethods.method(t);

return 0;
}

The problem with this solution is that I have to create for each
method a corresponding static function, can you contrive a solution
which doesn't require this?

Many thanks in advance for any advice.


You want to use class member pointers:

// Declare:

class Foo {

public:
void x();
void y();
};

// Don't use arrays, when you really want a map:

std::map<std::string, void (Foo::*)() > methods;

// Initialize:

methods["x"]= &Foo:x;
methods["y"]= &Foo:y;

// Invoke some method on an object.

void callFoo(Foo *obj, std::string methodname)
{
std::map<std::string, void (Foo::*)() >::iterator p=
methods.find(methodname);

if (p == methods.end())
throw "You are a bozo";

(obj->*(p->second))();
}


Hi Ondra and Sam, yes I finally got in touch with the
member pointers feature of C++, thank you so much for your hints and
explanations!! :)

I already posted a solution using the memeber pointers, well now I see
I should rather use std::map rather than a plain array.

Best regards.
 
S

Stefano Sabatini

Stefano Sabatini writes: [...]
The problem with this solution is that I have to create for each
method a corresponding static function, can you contrive a solution
which doesn't require this?

Many thanks in advance for any advice.

You want to use class member pointers:

// Declare:

class Foo {

public:
void x();
void y();
};

// Don't use arrays, when you really want a map:

std::map<std::string, void (Foo::*)() > methods;

// Initialize:

methods["x"]= &Foo:x;
methods["y"]= &Foo:y;

// Invoke some method on an object.

void callFoo(Foo *obj, std::string methodname)
{
std::map<std::string, void (Foo::*)() >::iterator p=
methods.find(methodname);

if (p == methods.end())
throw "You are a bozo";

(obj->*(p->second))();
}

Hi Ondra and Sam, yes I finally got in touch with the
member pointers feature of C++, thank you so much for your hints and
explanations!! :)

I already posted a solution using the memeber pointers, well now I see
I should rather use std::map rather than a plain array.

And here it is a solution using map:

#include <string>
#include <iostream>
#include <map>

using namespace std;

class DumbThing {
public:
void sayFoo() { cout << "Foo!" << endl; }
void sayBar() { cout << "Bar!" << endl; }
};

int main(void) {
// declare a map
map<string, void (DumbThing::*)() > methods;

// initialize it
methods["sayFoo"] = &DumbThing::sayFoo;
methods["sayBar"] = &DumbThing::sayBar;

map<string, void (DumbThing::*)() >::iterator it;

DumbThing t;
for (it=methods.begin() ; it != methods.end(); it++ ) {
cout << "Invoking method: " << (*it).first << endl;
(t.*(it->second))();
}

return 0;
}

Best regards.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top