• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1817
  • Last Modified:

function pointer in C++

when I ran this code

//File test.h
class test  
{
public:
   void f1(int n,void (*visit)(int));
   void print(int);
   void output();
};
 
//File test.cpp
#include "test.h"
#include <iostream.h>
 
void test::f1(int n,void (*visit)(int)) // Truyen vao con tro ham visit
{
     (*visit)(n);
}
 
void test::print(int n)
{
     cout << n << endl;
}
 
 
void test::output()
{
     int n = 10;
     f1(n,&print); // Truyen con tro ham print vao
}  

void main()
{
    test a;
    int n = 10;
    a.f1(n,&print);
}

it has an error like this:
error C2276: '&' : illegal operation on bound member function expression  


but when I write print function out of the test class:

void print(int n)
{
     cout << n << endl;
}

the code  ran normally. SO explain what is the diffrence between these situation. Thanks a lot
0
meoconx
Asked:
meoconx
1 Solution
 
UrosVidojevicCommented:
You can't take address of an non-static function.

So that function should be static or outside the class.
0
 
UrosVidojevicCommented:
ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say `&test::print'
0
 
meoconxAuthor Commented:
thanks for replying.
0
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.

 
Infinity08Commented:
What you want to do is a member function pointer, not a function pointer. Use :

        void (test::*visit)(int)

instead of :

        void (*visit)(int)

to define the function pointer.

And assign the address like this :

        &test::print

instead of :

        &print

And inside the f1 method, you call it using :

        (*this.*visit)(n);

instead of :

        (*visit)(n);


So, the code becomes :

#include <iostream>
 
class test {
public:
   void f1(int n, void (test::*visit)(int));
   void print(int);
   void output();
};
 
void test::f1(int n, void (test::*visit)(int)) {
     (*this.*visit)(n);
}
 
void test::print(int n) {
     std::cout << n << std::endl;
}
 
 
void test::output() {
     int n = 10;
     f1(n, &test::print);
}  

int main(void) {
    test a;
    int n = 10;
    a.f1(n, &test::print);
    return 0;
}

Note that I also changed the return type of main to int (mandatory) and used the <iostream> header instead of the deprecated <iostream.h> header
0
 
Infinity08Commented:
>> You can't take address of an non-static function.

Sure you can. You just have to make sure to call it on a valid object that goes with the method.
0
 
jkrCommented:
Furthermore, you cannot use member function pointers without an instance of the class they belong to. This has to be

//File test.h
class test  
{
public:
   void f1(int n,void (test::*visit)(int));
   void print(int);
   void output();
};
 
//File test.cpp
#include "test.h"
#include <iostream.h>
 
void test::f1(int n,void (test::*visit)(int)) // Truyen vao con tro ham visit
{
    test* p = this;

     (p->*visit)(n);
}
 
void test::print(int n)
{
     cout << n << endl;
}
 
 
void test::output()
{
     int n = 10;
     f1(n,&test::print); // Truyen con tro ham print vao
}  

void main()
{
    test a;
    int n = 10;
    a.f1(n,&test::print);
}


See also http://www.function-pointer.org/
0
 
Infinity08Commented:
One more note : it's better to use Test (with capital T) as your class name - it makes it easier to recognize types.

Btw, I hope that your code was just intended to illustrate something, because there's no sense in doing what you do (you can just call print directly without passing through f1).
0
 
itsmeandnobodyelseCommented:
>>>> because there's no sense in doing what you do

Generally, pointers of member functions are of less importance. I do know only one single library where they were used as a major concept (MFC message mapping) and even there the pointers needed to be casted so that they prevent from using multiple inheritance when deriving from MFC classes.

The problem is taht as you need an object and a function of the class, you much more easily could call the function directly or use a static member function pointer and pass the object as an argument:

class D : public B
{
 public:
      static void sfunc(B* b, int i)
        { b->vfunc(i; }
      virtual void vfunc(int i) { doanyvirtualornot(); }
       
};

look at the class above:

if you have

    D d;
    int i = 5;

the easiest of course is to simply call

   d.vfunc(i);

In case of a function that takes a B*, a static function pointer and an integer you have

  // sorry I always use a typedef because of the weird syntax
  typedef  void (*SFunc) (int);  
  void Anyclass::anyfunc(B* b, SFunc func, int i)
  {
       func(b, i);
  }

and - I would say - it is rather simple and straight-forward.

     func(b, i);  

turns the static call to a virtual call. In case of member function pointers you'll have a mess like that:

  typedef void (D::*DMFunc)(int);
  void Otherclass::otherfunc(B* b, DMFunc func, int i)
  {
      (*b).*func(i);   // error: D::*DMFunc is not a member

      D* d = dynamic_cast<D*>(b);  
      (*d).*func(i);   // ok

  }

If not using typedef's the above is still more horrifying.

Regards, Alex



0
 
Infinity08Commented:
I noticed that you gave a B grade. That usually means that the answer was not satisfactory. Is there something you're still not clear about ? You can always ask for clarifications ! We want to give you the best help possible :)
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now