Solved

Passing functions as arguments to other functions

Posted on 2000-03-01
12
200 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
 
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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 22

Accepted Solution

by:
nietod earned 150 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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

707 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now