Search code examples
c++functionpointersnamespacesampersand

About Function Pointer in C++


  1. Do these lines mean the same? Both works without any warning messages!

int (*pFunc)() = func1;     // I learned this is right.
int (*pFunc)() = &func1;        // Works well with an ampersand too.
  1. Why do I have to put an ampersand in this case? Without it, doesn't work!

int (CMyClass::*pMemberFunc)() = &CMyClass::memberFunc1;
  1. Why do I have to specify namespace for functions in Classes even if the type of the function pointer matches exactly?

int (*pMemberFunc)() = CMyClass::memberFunc1;       // Compiler error
int (*pMemberFunc)() = &CMyClass::memberFunc1;      // Compiler error
  1. Why can't I specify namespace in this case?

namespace myNamespace {
    int func1() {}
}

int (myNamespace::*pFunc)() = myNamespace::func1;       // Compiler error
int (myNamespace::*pFunc)() = &myNamespace::func1;      // Compiler error

int (*pFunc)() = &myNamespace::func1;       // Works!

Solution

  • Your first question, legalese of the Standard:

    A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses. [Note: that is, the expression &(qualified-id), where the qualified-id is enclosed in parentheses, does not form an expression of type “pointer to member.” Neither does qualified-id, because there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to member function” as there is from an lvalue of function type to the type “pointer to function” (4.3). Nor is &unqualified-id a pointer to member, even within the scope of the unqualified-id’s class. —end note ]

    While it seems inconsistent at first, I do like the fact that it makes the semantics for pointers to members (be them functions or not) equivalent. This certainly has benefits when dealing with templates and decltype.

    For the second question, you scope the pointer variable with CMyClass because yours is not a simple "() -> int" function: memberFunc1() is implicitly passed a CmyClass* argument you normally refer to as "this".

    If you could truly pass nothing, you'd be missing information (and possibly crash) for the method to do its job correctly. If you're accustomed to "delegates" in other languages, do remember these can optionally store a "Target" pointer to the "this" object if the method is not static/global.

    As for the third, it's a free standing function, so it's truly () -> int, but you're attempting to scope your pointer to the namespace, when in fact you're not declaring your variable inside the namespace block.

    While the namespace certainly alters how symbols are searched for, it doesn't affect the convention call of the function at all.