473,400 Members | 2,145 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,400 software developers and data experts.

Function Pointers - design question.

Hi Guys, I have a couple of problems. The first is (I believe) a simple
syntactic problem you can probably solve quite easily. The second is a
design style problem which might be more tricky...

So, I have a class with a couple of integers. I provide a couple of
functions to operate on those integers (add, subtract) and the function
to be called is chosen via a function pointer. Like so:

01: #include <iostream>
02:
03: class MyClass
04: {
05: public:
06: MyClass(int xToSet, int yToSet):x(xToSet), y(yToSet){};
07:
08: void setOperationToAdd(void)
09: {
10: performOperation = add;
11: }
12:
13: void setOperationToSubtract(void)
14: {
15: performOperation = subtract;
16: }
17:
18: //Pointer to an operation.
19: int (MyClass::*performOperation)(void);
20:
21: protected:
22: int add(void){return x + y;};
23: int subtract(void){return x - y;};
24: int x;
25: int y;
26: };
27:
28: int main()
29: {
30: MyClass test(10,20);
31: test.setOperationToAdd();
32: std::cout << test.performOperation() << std::endl;
33: test.setOperationToSubtract();
34: std::cout << test.performOperation() << std::endl;
35:
36: return 0;
37: }

Visual Studio gives the error:

error C2064: term does not evaluate to a function taking 0 arguments

for lines 32 and 34. Any idea what the problem is?

Ok, now for the design problem. I wish to allow the user of my class to
specify their own operations (e.g. multiply, divide). The problem I have
is that these new functions are declared outside the class, they are not
member functions (because presumably the user wouldn't be able to modify
my class). Now, pointers to member functions (such as the one i've
declared) cannot point to normal functions because of the implicit
'this' parameter. How should I solve this?

1) I could require my users to subclass 'MyClass' if they want to add
new functions. Their new functions would then be members and so could be
pointed to. This has the advantage that they can directly access the
protected parts without accessor functions but seems a bit of a burden
on the user.

2) I read (briefly) about funtionoids in the FAQ's. It seens they can be
used when functions have varying parameters as common ones get passed to
the constructor of the functionoid and un-common ones get passed when
the functionoid is called. Can these be used in this situation?

Any furthers ideas?

Thanks in advance,

David
Feb 5 '06 #1
2 3272
David Williams wrote:
Hi Guys, I have a couple of problems. The first is (I believe) a simple
syntactic problem you can probably solve quite easily. The second is a
design style problem which might be more tricky...
My answer and opinions after your code below:

So, I have a class with a couple of integers. I provide a couple of
functions to operate on those integers (add, subtract) and the function
to be called is chosen via a function pointer. Like so:

01: #include <iostream>
02:
03: class MyClass
04: {
05: public:
06: MyClass(int xToSet, int yToSet):x(xToSet), y(yToSet){};
07:
08: void setOperationToAdd(void)
09: {
10: performOperation = add;
11: }
12:
13: void setOperationToSubtract(void)
14: {
15: performOperation = subtract;
16: }
17:
18: //Pointer to an operation.
19: int (MyClass::*performOperation)(void);
20:
21: protected:
22: int add(void){return x + y;};
23: int subtract(void){return x - y;};
24: int x;
25: int y;
26: };
27:
28: int main()
29: {
30: MyClass test(10,20);
31: test.setOperationToAdd();
32: std::cout << test.performOperation() << std::endl;
33: test.setOperationToSubtract();
34: std::cout << test.performOperation() << std::endl;
35:
36: return 0;
37: }

Visual Studio gives the error:

error C2064: term does not evaluate to a function taking 0 arguments

for lines 32 and 34. Any idea what the problem is?
std::cout << (test.*(test.performOperation))()
<< std::endl;

Ok, now for the design problem. I wish to allow the user of my class to
specify their own operations (e.g. multiply, divide). The problem I have
is that these new functions are declared outside the class, they are not
member functions (because presumably the user wouldn't be able to modify
my class). Now, pointers to member functions (such as the one i've
declared) cannot point to normal functions because of the implicit
'this' parameter. How should I solve this?
The design is ill-formed. Your idea can be directly expressed by better
encapsulating MyClass. For example:

class MyClass{
int m_x, m_y;

public:
MyClass(int _x, int _y){m_x = _x; m_y = _y;}

int x(void) const {return m_x;}
int y(void) const {return m_y;}
};

int add(const MyClass& i){return i.x() + i.y();}
int subtract(const MyClass& i){return i.x() - i.y();}
int main(void)
{
MyClass test(8, 2);
int a = add(test); // a = 10
int b = subtract(test); // b = 6

return 0;
}

1) I could require my users to subclass 'MyClass' if they want to add
new functions. Their new functions would then be members and so could be
pointed to. This has the advantage that they can directly access the
protected parts without accessor functions but seems a bit of a burden
on the user.
If you do this, you will have to provide virtual functions at least.
This is unnecessary and it breaks encapsulation. The idea is to shield
the vast amount of add-on functionality from the core, so that changing
the core would not need a rewrite of every single add-on function.

And plus, setting and resetting the behavior of a particular function of
a class is not a good idea. Users can be quite confused.

2) I read (briefly) about funtionoids in the FAQ's. It seens they can be
used when functions have varying parameters as common ones get passed to
the constructor of the functionoid and un-common ones get passed when
the functionoid is called. Can these be used in this situation?
I'm not so sure about what you mean but I guess you want an adapter to
work your class with function objects in <functional>. This can be done
quite easily once you have properly encapsulate your class:

// with the same class definition I gave you:

template <typename Op>
int perform(const MyClass& i, Op op)
{
return op(i.x(), i.y());
}

int c = perform(test, std::plus<int>());
int d = perform(test, std::minus<int>());

And yes, you can add function objects to have broader use.

Any furthers ideas?

Thanks in advance,

David


Regards,
Ben
Feb 5 '06 #2
benben wrote:
David Williams wrote:
Hi Guys, I have a couple of problems. The first is (I believe) a
simple syntactic problem you can probably solve quite easily. The
second is a design style problem which might be more tricky...


My answer and opinions after your code below:

So, I have a class with a couple of integers. I provide a couple of
functions to operate on those integers (add, subtract) and the
function to be called is chosen via a function pointer. Like so:

01: #include <iostream>
02:
03: class MyClass
04: {
05: public:
06: MyClass(int xToSet, int yToSet):x(xToSet), y(yToSet){};
07:
08: void setOperationToAdd(void)
09: {
10: performOperation = add;
11: }
12:
13: void setOperationToSubtract(void)
14: {
15: performOperation = subtract;
16: }
17:
18: //Pointer to an operation.
19: int (MyClass::*performOperation)(void);
20:
21: protected:
22: int add(void){return x + y;};
23: int subtract(void){return x - y;};
24: int x;
25: int y;
26: };
27:
28: int main()
29: {
30: MyClass test(10,20);
31: test.setOperationToAdd();
32: std::cout << test.performOperation() << std::endl;
33: test.setOperationToSubtract();
34: std::cout << test.performOperation() << std::endl;
35:
36: return 0;
37: }

Visual Studio gives the error:

error C2064: term does not evaluate to a function taking 0 arguments

for lines 32 and 34. Any idea what the problem is?


std::cout << (test.*(test.performOperation))()
<< std::endl;

Ok, now for the design problem. I wish to allow the user of my class
to specify their own operations (e.g. multiply, divide). The problem I
have is that these new functions are declared outside the class, they
are not member functions (because presumably the user wouldn't be able
to modify my class). Now, pointers to member functions (such as the
one i've declared) cannot point to normal functions because of the
implicit 'this' parameter. How should I solve this?


The design is ill-formed. Your idea can be directly expressed by better
encapsulating MyClass. For example:

class MyClass{
int m_x, m_y;

public:
MyClass(int _x, int _y){m_x = _x; m_y = _y;}

int x(void) const {return m_x;}
int y(void) const {return m_y;}
};

int add(const MyClass& i){return i.x() + i.y();}
int subtract(const MyClass& i){return i.x() - i.y();}
int main(void)
{
MyClass test(8, 2);
int a = add(test); // a = 10
int b = subtract(test); // b = 6

return 0;
}

1) I could require my users to subclass 'MyClass' if they want to add
new functions. Their new functions would then be members and so could
be pointed to. This has the advantage that they can directly access
the protected parts without accessor functions but seems a bit of a
burden on the user.


If you do this, you will have to provide virtual functions at least.
This is unnecessary and it breaks encapsulation. The idea is to shield
the vast amount of add-on functionality from the core, so that changing
the core would not need a rewrite of every single add-on function.

And plus, setting and resetting the behavior of a particular function of
a class is not a good idea. Users can be quite confused.

2) I read (briefly) about funtionoids in the FAQ's. It seens they can
be used when functions have varying parameters as common ones get
passed to the constructor of the functionoid and un-common ones get
passed when the functionoid is called. Can these be used in this
situation?


I'm not so sure about what you mean but I guess you want an adapter to
work your class with function objects in <functional>. This can be done
quite easily once you have properly encapsulate your class:

// with the same class definition I gave you:

template <typename Op>
int perform(const MyClass& i, Op op)
{
return op(i.x(), i.y());
}

int c = perform(test, std::plus<int>());
int d = perform(test, std::minus<int>());

And yes, you can add function objects to have broader use.

Any furthers ideas?

Thanks in advance,

David


Regards,
Ben


Thanks, your code fixed the syntax problem I was having. Regarding the
design it seems my design was somewhat flawed - the functionoid /
function object approach does seems better. I think I'll read around it
some more though...

Regards,

David
Feb 6 '06 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Newsgroup - Ann | last post by:
Gurus, I have the following implementation of a member function: class A { // ... virtual double func(double v); void caller(int i, int j, double (* callee)(double)); void foo() {caller(1,...
1
by: jon wayne | last post by:
Hi Am trying to replace the classic switch case construct (am workng on a telecom stack devlpmnt)with an array of function ptrs. The problm am facing is that of indexing. - the case vals can be...
7
by: George Marshall | last post by:
Hi all, my question is what should I do with a pointer to be used inside a function ? The following function should take a pointer to a null terminated array of chars, do something with it, and...
12
by: Lance | last post by:
VB.NET (v2003) does not support pointers, right? Assuming that this is true, are there any plans to support pointers in the future? Forgive my ignorance, but if C# supports pointers and C# and...
20
by: asdf | last post by:
True or false ?
43
by: Tony | last post by:
I'm working with GUI messaging and note that MFC encapsulates the message loop inside of a C++ class member function. Is this somehow inherently less robust than calling the message loop functions...
40
by: gert | last post by:
#include <stdio.h> obj function hello(){ struct obj = { char *data = 'hello'} obj.add = obj_add(obj); return obj; } void function obj_add(obj){ obj function add(value){
3
by: googlinggoogler | last post by:
Hi This should all be pretty standard C stuff, but I'm going to use terms like mouse callback to communicate what Im tyring to do. Basically I have my program whirling around in an infinite...
5
by: Immortal Nephi | last post by:
I would like to design an object using class. How can this class contain 10 member functions. Put 10 member functions into member function pointer array. One member function uses switch to call...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.