Keep getting error C2064

D619d95cddb1edb227f51ef539d15cdc
0
Nautilus 103 Sep 10, 2005 at 23:39

Greetings,
I have problems with pointers to class-member functions.

I’m using Ms VC++ 6.0 Enterprise Ed. (with ServicePack 6)
Under WinXP Pro (if it makes any difference).

The problem is that (apparently) I can declare and initialize a pointer
to a member of a Class. No errors/warnings during compilation.
But when I dereference the pointer to call the function, I get the error
C2064:

“term does not evaluate to a function”

I searched through MSDN to no avail. Few articles found, and of no help.

One of them suggested to change my project settings (/vms /vmm…), but I
have tried all combinations and nothing worked.
Another article suggested to not use the ‘this’ pointer when dereferencing,
but it didn’t solve my problem.

I’m not a genius of C++… Please help me.

Roughly this is my situation:
Two classes: A and B.
Class A contains a useful method.
Class B first setup a pointer to Class A method; then automatically calls it
whenever the main program needs to do certain things with Class B.

Also, it’s not a small project and everything is wrapped up in a namespace (if it makes any difference).

Here is a code that produces the error:
(namespace is omitted)

//
// TYPEDEF
//
typedef void (CFunc::*FP) (void); // FP is a pointer to a function (member of class CFunc) that
                 // receives no arguments and returns no arguments.
                 // Yep, same type as 'CFunc::Blah()' prototype.

//
// CLASSES
//
class CFunc
{
  public:
    void Blah (void); // <--- we want to setup a pointer to this function.
};

void CFunc::Blah (void)
{
  // do something...
}



class CCall
{
  private:
    FP pfnBlah; // declares a pointer to 'CFunc::Blah()' (see typedef above).
          // Whether this pointer is private or public, makes no difference:
          // works either way (apparently!).

  public:
    void SetFuncPtr (FP pFunc)
    {
      this->pfnBlah = pFunc; // setup our pointer.
    };

    void DoSomething (void)
    {
      ////////////////////////////////////////////////////
      // Let's use our pointer to call 'CFunc::Blah()'.

      // without dereferencing.
      this->pfnBlah (); // <--- error C2064 "tern does not evaluate to a function".

      // by dereferencing.
      *(this->pfnBlah) (); // <--- fails as well... error C2064

      // NOTE : I also tried both calls without the 'this' pointer. Didn't work.
    };    
};



//
// MAIN
//
void main (void)
{
  // Istantiate our two classes.
  CFunc clsFunc;
  CCall clsCall;



  // Calls 'CCall::SetFuncPtr()' method to setup a function pointer pointing to 'CFunc::Blah()'.
  // So far things work and no error or warning is raised when compiling.

  clsCall.SetFuncPtr (clsFunc.Blah);



  // Now let's make class 'CCall' USE its pointer to 'CFunc::Blah()' method.

  clsCall.DoSomething ();
}

Thanks in advance for any help!
Best regards.

5 Replies

Please log in or register to post a reply.

4e70f904a74bd2aa8773733b25b77d41
0
SigKILL 101 Sep 11, 2005 at 09:25

Well, what you are trying won´t work unless Blah is a static function. The problem is that an instance of the class is required in order for you to call member functions (or access member variables) that are not static. Make sure you know what the static keyword means in a class before trying to use it…

-si

62fcdcb04132f1e4fc481b4467cb694c
0
Isjtar 101 Sep 11, 2005 at 09:49

SigKILL is right, you need an instance of a class to call a member function. Remember that a function is just a pointer in memory that is the same for each instance of a class, and without a pointer to the actual class data, it won’t be able to do much. As SigKILL said, you might be able to pull this off with a static member function, as a function of this type cannot access class data. But that’s probably not what you want. Try the code below to get your sample working. Remember that if you to keep your code compatible, you’ll need to use the “&class::function” notation for class function pointers, as some compilers won’t allow the notation you’re using.

//
// TYPEDEF
//

//
// CLASSES
//
class CFunc
{
public:
    void Blah (void); // <--- we want to setup a pointer to this function.
};

void CFunc::Blah (void)
{
    // do something...
}

typedef void (CFunc::*FP) (void); // FP is a pointer to a function (member of class CFunc) that
// receives no arguments and returns no arguments.
// Yep, same type as 'CFunc::Blah()' prototype.

class CCall
{
private:
    CFunc   *m_pClass;
    FP pfnBlah; // declares a pointer to 'CFunc::Blah()' (see typedef above).
    // Whether this pointer is private or public, makes no difference:
    // works either way (apparently!).

public:
    void SetFuncPtr (CFunc *a_pClass, FP pFunc)
    {
       m_pClass = a_pClass;
       this->pfnBlah = pFunc; // setup our pointer.
    };

    void DoSomething (void)
    {
 ////////////////////////////////////////////////////
 // Let's use our pointer to call 'CFunc::Blah()'.

        (*(m_pClass).*(pfnBlah))();
    };    
};



//
// MAIN
//
void main (void)
{
    // Istantiate our two classes.
    CFunc clsFunc;
    CCall clsCall;



    // Calls 'CCall::SetFuncPtr()' method to setup a function pointer pointing to 'CFunc::Blah()'.
    // So far things work and no error or warning is raised when compiling.

    clsCall.SetFuncPtr (&clsFunc, &CFunc::Blah);



    // Now let's make class 'CCall' USE its pointer to 'CFunc::Blah()' method.

    clsCall.DoSomething ();
}
D619d95cddb1edb227f51ef539d15cdc
0
Nautilus 103 Sep 11, 2005 at 14:39

Well, I was gonna post how stupid I can be for making such mistakes… but you
already solved my problem :blush:

I will try your code, Isjtar. Thank you.
Although a static member function doesn’t suit me in this case, I’ll keep it in mind
for the future, SigKILL. Thanks to you too.

Anyway, I have just found another solution on an old web page (page that was
nowhere to be found before posting my help request… lovely :mad: ).
Here is a simplified version of the sample code:

class Foo
{
    public:
        void Loo (void); // <--- We'll setup a pointer to this member.
};



void main (void)
{
    // Pointer declaration.
    // --------------------
    // Do not confuse what follows '=' with the assignment of a function address.
    // However, this line cannot be placed inside a class declaration (.h)
    // without raising an error.
    // But (for example) we can make it a global pointer inside the class
    // implementation module (.cpp)

    void (Foo::*pfnLoo) (void) = &Foo::Loo; // <--- Note the '= &Foo::' part here.
                                            //      Foo is the class name, not the
                                            //      name of a Foo class instance.

    Foo cMoo; // <--- Instantiate Foo class. As usual.

    (cMoo.*pfnLoo) (); // <--- Dereference to call. No compiler errors.
}

Can you believe I refused to ask for help on this for almost 2 weeks?!? :wallbash:

    me->bIdiot = true; // deserved. feel free to agree.

Best regards everyone,
ciao ciao.

065f0635a4c94d685583c20132a4559d
0
Ed_Mack 101 Sep 11, 2005 at 16:28

Don’t feel stupid, you’re learning and that’s not a stupid trait/activity.

D619d95cddb1edb227f51ef539d15cdc
0
Nautilus 103 Sep 12, 2005 at 22:00

Yours are kind words, Ed, but I should have asked for help sooner.
Look at that sample syntax. I would have never got it on my own…

Lesson learned.

I have one question. The dude who wrote the web page explained that this kind of
pointers are rarely needed/used, hence not everyone knows how to correctly set them up.

By looking at the unusual syntax, I guess he’s right about the ‘not everyone’ part.
But why does he say ‘rarely’? What other methods could be used to make two separate
classes interact without using the (client) program as intermediary?

Best regards,
ciao.