Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Passing functions as arguments to other functions

Posted on 2000-03-01
12
Medium Priority
?
247 Views
Last Modified: 2010-05-18
Ok, the subject kind of sais it all, what i'm trying to do is pass a class function to another classe's function, i've tried this way and it's failing:

typedef void (*rec_function_ptr)(CString);
typedef void (*close_function_ptr)(int);

to define function passing, then the function that takes functions was defined as follows:

CConnectSocket(rec_function_ptr onReceiveFunc, close_function_ptr onCloseFunc);

and the functions i'm passing are:

  void ConnectionClose(int errCode);
  void ParseData(CString str);


Now when i try to compile i get this error

error C2664: 'CConnectSocket::CConnectSocket' : cannot convert parameter 1 from 'void (class CString)' to 'void (__cdecl *)(class CString)


can anyone pleaseee tell me what i'm doing wrong?! i've been trying to figure this thing out for over an hour now :(

Thank you
0
Comment
Question by:gkanaan
  • 8
  • 4
12 Comments
 
LVL 22

Expert Comment

by:nietod
ID: 2575139
>> what i'm trying to do is pass a class function
>> to another classe's function
Its hard to see that in the code you produced, but if that is the case, then the code is wrong.  

A pointer to class's non-static member function has a special type, it is called a "pointer-to-member" and it may be represented in a different way than other pointers.  The syntax for using it is also a little different--for good reason.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 2575150
Lets take the first example

typedef void (*rec_function_ptr)(CString);

say you have a non-static ember function that takes a CString as a data member like

class Cls
{
public:
   void F1(CString);
};

You would probably say that the funciton F1 takes only one parameter, right?   Well actually no, it takes two.  There is a 2nd parameter that is "hidden"  i.e. you don't declare it.  It is the "Cls" object that function is suppoed to work with.  This parameter is passed as the "this" pointer.

Why do I mention this?  well it means that a non-member function declared like

void F2(CString);

is inheritently different than the member function, this is because it does not have that hidden parameter.

continues
0
 

Author Comment

by:gkanaan
ID: 2575153
Yes i've looked around some previous similar questions and found a solution however since i'm kind of a beginner in C++ i got lost reading it, it seems quite complicated if i want to pass member function as an argument from 2 different classes, so i'm dropping the idea for now, thanks anyway...
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 22

Expert Comment

by:nietod
ID: 2575169
Since the member and non-member functions are inheriently different, the pointers to them are also inhierently different and are not interchangable.  a pointer to a member function must be declared as in this example.

class Cls
{
   int Add(int i1,int i2) { return i1 + i2 };
   int Subd(int i1,int i2) { return i1 - i2 };
   int Abs(int i) { return i <0? -1*i:i; };
}

// member function pointer typedef.  Not
// necessary, except for readability.
typedef int (Cls::*MbrFunPtrTyp)(int,int);
// This type is a pointer to a member function of Cls that
// takes 2 ints as parameters and returns a int.  
// Thus this type of pointer can point to Add() or Sub()
// but not to Abs().

Now the when the member function pointer is used to call the member function and object must be supplied for the function to work with.  This is the "this" object.  So member functions are called with a unique sintax as follows.

// Declare and use a pointer of this type.
MbrFunPtrTyp FunPtr = &Cls::Add; // make pointer to add function.
Cls C;                             // Declare object of the class
Cls *CPtr = &C;            // Declare pointer to object of the class.

int R1 = (C.*FunPtr)(1,2); // Add 1 and 2 using a Cls object.
int R2 = (CPtr->*FunPtr)(1,2); // Add 1 and 2 using a pointer to a Cls object.

FunPtr = &Cls::Sub; // Make pointer to Sub function.

int R3 = (C.*FunPtr)(1,2); // Subtract1 and 2 using a Cls object.
int R4 = (CPtr->*FunPtr)(1,2); // Subtract 1 and 2 using a pointer to a Cls object.

Note that the functions that the pointer-to-member pointer will be used with must have the same signature.  To be precise they must:

1. be members of the same class.
2. have the same parameters.
3. have the same return value
4. Have the same calling convention.  (in other words, all must be virtual or none must be virtual.  all must be cdecl, or all must be extern "C" etc.)

Thus the example above the function pointer could be used with Add() and Sub(), but not with Abs().  You could define a seperate function pointer type that could be used with Abs() and other member functions of Cls that have the same parameters and signature etc.

Let me know if you have any questions
0
 
LVL 22

Expert Comment

by:nietod
ID: 2575174
>> so i'm dropping the idea for now, thanks anyway...
Huh?   I've answered the question.  Now it is a little late to drop it!
0
 

Author Comment

by:gkanaan
ID: 2575186
Ok sorry i didn't know you were answering all, i only had read your first comment, however, what you're explaining is how to call a Specific class' function, what i need is to call a function in an abstract class, say i have (not C++ specific format, just to be fast)

Class B {
  void funcB(CString a);
}

Class A {
  void funcA(CString a);
}

Class C {
  C(func_ptr fptr);
  void example();
}

As you see here the class C should be able to take any function if it's from class A or B as long as it has the same signature (that is what i'm trying to accomplish)...
do you get my point?  
0
 
LVL 22

Accepted Solution

by:
nietod earned 300 total points
ID: 2575234
That is logically impossible.  it is not a matter of syntax it is that that sort of design makes no sense.  

Non static member functions have these hidden parameters that they may work on.  Right?  Well can you specify the correct type of parameter if the parameter type changes depending on the function to be called?  seee the problem.  

Now if these functions don't need to work on the "hidden parameter"   i.e. if then don't need to access any of the classes data members or non-static functions.  Then you can just declare these functions as static members, like

class A
{
   static void FunctA(CString a)
};

In this case the functions will not be passed the extra hidden parameter.  That means all there functiosn will have the same signature (same parameters) and will act like ordinary functions.  That is, ordinary function pointers are used to call the functions.  None of the weird syntax above is needed.

Now that works only if the functions don't access the class's data members.  if they do, you have more trouble.  You can still make it work, but only by calling "interface functions"  These are ordinary functions  (i.e. non-member functions or static member functiosn (no hidden this parameter.)  These interface functions will then call the non-static member function using an object that they retreive  in some way, like as a parameter .  Like for example

class A
{
   void FunA(CString s); // non-static we ultimately want to call.
   static void Interface(void *ObjPtr,CString s) // static interface function.
   {
       A* ThisPtr = (A*)ObjPtr; // get object to be used.
       ObjPtr->FunA(s);  // Call the non-static
   };
};

See how this interface function gets an object to make the non-static call with.  In this case the object comes from the parameters.  It could come fom a global varaible or from a table or other source.  Then once it has the object, it makes the call using it.

Note that in the fucntion, the object pointer is passed using a void* pointer.  not a A* pointer.  This is so that the interface function has the same signature (parameters) as the interface functions of the other classes.  That way one pointer type can be used too call any of the interface functions.

Now this means that when you use this design, you must specify an object and an function pointer that work together.  i.e you can't specify the pointer to class B's interface function and a pointer to an object of class A.  That will cause unpredicatable behaviour.

Does that make sense?
0
 
LVL 22

Expert Comment

by:nietod
ID: 2576242
gkanaan,
  What is wrong?  I gave you two ways to accomplish what you wanted.  (depending on your needs.)
0
 

Author Comment

by:gkanaan
ID: 2576582
Yes thank you, i didn't read it last night because i was Very tired man, i just read the second option you gave and it seems quite logical and it should work, i'll try it...
Thanks
0
 
LVL 22

Expert Comment

by:nietod
ID: 2576648
Well you shouldn't grade a question until you have read it and all the discussion is finished.  The grade you give is permenantly stored in an expert's history.  I don't like get poor grades, especially after wroking so hard on a question.
0
 

Author Comment

by:gkanaan
ID: 2576663
i'm sorry i didn't pay attention i'm telling i wasn't quite awake, can i regrade in any way?
0
 
LVL 22

Expert Comment

by:nietod
ID: 2576695
Not now.  Just try to be more careful in the future.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

927 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question