473,785 Members | 2,440 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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(xToSe t), y(yToSet){};
07:
08: void setOperationToA dd(void)
09: {
10: performOperatio n = add;
11: }
12:
13: void setOperationToS ubtract(void)
14: {
15: performOperatio n = subtract;
16: }
17:
18: //Pointer to an operation.
19: int (MyClass::*perf ormOperation)(v oid);
20:
21: protected:
22: int add(void){retur n 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.setOperati onToAdd();
32: std::cout << test.performOpe ration() << std::endl;
33: test.setOperati onToSubtract();
34: std::cout << test.performOpe ration() << 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 3283
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(xToSe t), y(yToSet){};
07:
08: void setOperationToA dd(void)
09: {
10: performOperatio n = add;
11: }
12:
13: void setOperationToS ubtract(void)
14: {
15: performOperatio n = subtract;
16: }
17:
18: //Pointer to an operation.
19: int (MyClass::*perf ormOperation)(v oid);
20:
21: protected:
22: int add(void){retur n 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.setOperati onToAdd();
32: std::cout << test.performOpe ration() << std::endl;
33: test.setOperati onToSubtract();
34: std::cout << test.performOpe ration() << 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.pe rformOperation) )()
<< 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(xToSe t), y(yToSet){};
07:
08: void setOperationToA dd(void)
09: {
10: performOperatio n = add;
11: }
12:
13: void setOperationToS ubtract(void)
14: {
15: performOperatio n = subtract;
16: }
17:
18: //Pointer to an operation.
19: int (MyClass::*perf ormOperation)(v oid);
20:
21: protected:
22: int add(void){retur n 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.setOperati onToAdd();
32: std::cout << test.performOpe ration() << std::endl;
33: test.setOperati onToSubtract();
34: std::cout << test.performOpe ration() << 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.pe rformOperation) )()
<< 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
9377
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, 2, func);
1
2213
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 any of 0- 0xFF(1 byte long) - but unfortunately as of now I just need to use about 15 of 'em. In the sense I can't just make an array of function ptrs - coz the case vals I need to use right now are high up in the range.
7
2352
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 write to the other pointer (*dest). Should I check if the *dest pointer is NULL or not before writing to it ? Should I realloc it before I write to it ? Should I free it if != NULL and
12
4095
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 VB.NET get compiled into the same code, then I don't understand why VB.NET can't support pointers Thanks for any info Lance
20
2066
by: asdf | last post by:
True or false ?
43
2094
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 within main? (It just doesn't "feel" right to me). Example 1: class MyProg { public:
40
2312
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
2018
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 loop (easy) waiting for the mouse to be clicked (I dont need help with this) and depending on user input a variable might define what function I want (be it line, circle....(again these are my issues)
5
3654
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 10 member functions. Can switch be replaced to member function pointer array? Please provide me an example of source code to show smart pointer inside class. Thanks....
0
9647
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9489
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10357
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8988
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6744
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5396
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5528
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3665
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2893
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.