INFO: Creating a Function Pointer to a C++ Member Function (Q94579)--------------------------------------------------------------------------------
The information in this article applies to:
Microsoft Visual C++, versions 1.0 , 1.5 , 1.51 , 2.0 , 2.1 , 4.0 
Microsoft Visual C++, 32-bit Enterprise Edition, version 5.0 
Microsoft Visual C++, 32-bit Professional Edition, version 5.0 
--------------------------------------------------------------------------------
SUMMARY
The text below describes generating a function pointer to a class member function in code compiled with Microsoft C/C++ version 7.0 or later. The declaration of a pointer to a class member function must include the class name. However, the class name is omitted from the declaration of a pointer to a static member function. MORE INFORMATION
In the C and C++ languages, an application can define a variable that contains the address of a function. You can call the function using this variable instead of through the function name. In C++, a pointer to a nonstatic member function contains the address of the function in the class, not in the object. To call the function, use the appropriate member selection operator (. or ->), the indirection operator (*), and the name of an object of the class. In most cases in the C language, function pointer declarations take the following form:    int (*ptr)();
This code declares a pointer to a function that returns an integer. The function accepts an unknown number of augments. To create a pointer to a C++ class member function, specify the class name in the function pointer declaration, as follows: 
   int (Sample::*ptr)();
This code declares a pointer to a member function in the Sample class that returns an integer. This function does not accept any arguments. The different ways to interpret the empty parentheses in function declarations is a major difference between the C and C++ languages. In C, a function pointer declaration that has no arguments is syntactically identical to the following: 
   int (*ptr)(...);
However, a C++ prototype declared without arguments is syntactically identical to the following: 
   int (Sample::*ptr)(void);
In C++, if the function accepts arguments, the types of the arguments must also be listed, as in the following: 
   int (Sample::*ptr2)(int, int);
In C, the types of the arguments may be listed in the same manner. A pointer to a static member function is declared in the same manner as a pointer to a C function. However, because the declaration is part of a C++ program, the declaration must list any arguments and their associated types. To determine the procedure address to assign to a pointer variable, use the class name and the scope resolution operator (::). This syntax provides flexibility because a declared variable can contain the address of any object of the class. The object name in the function call determines the copy of the function used. The sample code below demonstrates declaring and using pointers to a class member function and to a static member function. Note that when the arguments in the function pointer declaration do not match the arguments of the function assigned to the pointer, the compiler generates errors C2440 and C2564. For example, if the "int" declaration is omitted from the argument list declaration for the function pointer, the compiler generates the following error messages: 
16-bit 
error C2440: 'initializing' : cannot convert from 'void (__far __pascal Data::*)(int )__near ' to 'void (__far __pascal Data::*)(void )__near' error C2564: formal/actual parameters mismatch in call through pointer to function 
32-bit 
error C2440: 'initializing' : cannot convert from 'void (Data::*)(int) to 'void (Data::*)(void)" error C2197: 'void (Data::*)(void)' : too many actual parameters 
Sample Code 
/*
 * Compile options needed: None
 */ #include <iostream.h>class Data
{
private:
   int y;
   static int x;public:
   void SetData(int value) {y = value; return;};
   int GetData() {return y;};
   static void SSetData(int value) {x = value; return;};
   static int SGetData() {return x;};
};int Data::x = 0;void main(void)
{
   Data mydata, mydata2;   // Initialize pointer.
   void (Data::*pmfnP)(int) = &Data::SetData; // mydata.SetData;   // Initialize static pointer.
   void (*psfnP)(int) = &Data::SSetData;   mydata.SetData(5); // Set initial value for private data.
   cout << "mydata.data = " << mydata.GetData() << endl;   (mydata.*pmfnP)(20); // Call member function through pointer.
   cout << "mydata.data = " << mydata.GetData() << endl;   (mydata2.*pmfnP)(10) ; // Call member function through pointer.
   cout << "mydata2.data = " << mydata2.GetData() << endl;   (*psfnP)(30) ; // Call static member function through pointer.
   cout << "static data = " << Data::SGetData() << endl ;
}
For more information about parameter lists in function declarations and how these are handled by C and C++, please see the following article in the Microsoft Knowledge Base:  

解决方案 »

  1.   

    INFO: Passing a Pointer to a Member Function to the Win32 API (Q102352)
    4.00 | 3.10 3.50 3.51 WINDOWS | WINDOWS NT kbprg 
    --------------------------------------------------------------------------------
    The information in this article applies to:
    Microsoft Win32 Application Programming Interface (API), used with: 
    Microsoft Windows NT Server versions 3.1 , 3.5 , 3.51 
    Microsoft Windows NT Workstation versions 3.1 , 3.5 , 3.51 
    Microsoft Windows 95 
    --------------------------------------------------------------------------------
    SUMMARY
    Many of the Win32 application programming interfaces (APIs) call for a callback routine. One example is the lpStartAddr argument of CreateThread():    HANDLE CreateThread(lpsa, cbStack, lpStartAddr, lpvThreadParm,
    fdwCreate, lpIDThread)    LPSECURITY_ATTRIBUTES lpsa;    /* Address of thread security attrs */ 
       DWORD cbStack;                    /* Initial thread stack size*/ 
       LPTHREAD_START_ROUTINE lpStartAddr; /* Address of thread function */ 
       LPVOID lpvThreadParm;       /* Argument for new thread*/ 
       DWORD fdwCreate;               /* Creation flags*/ 
       LPDWORD lpIDThread;               /* Address of returned thread ID */ 
    When attempting to use a member function as the thread function, the following error is generated: 
       error C2643: illegal cast from pointer to member
    The problem is that the function expects a C-style callback, not a pointer to a member function. A major difference is that member functions are called with a hidden argument called the "this" pointer. In addition, the format of the pointer isn't simply the address of the first machine instruction, as a C pointer is. This is particularly true for virtual functions. If you want to use a member function as a callback, you can use a static member function. Static member functions do not receive the "this" pointer and their addresses correspond to an instruction to execute. Static member functions can only access static data, and therefore to access nonstatic class members, the function needs an object or a pointer to an object. One solution is to pass in the "this" pointer as an argument to the member function. MORE INFORMATION
    This situation occurs with callback functions of other types as well, such as:    DLGPROC                  GRAYSTRINGPROC
       EDITWORDBREAKPROC        LINEDDAPROC
       ENHMFENUMPROC            MFENUMPROC
       ENUMRESLANGPROC          PROPENUMPROC
       ENUMRESNAMEPROC          PROPENUMPROCEX
       ENUMRESTYPEPROC          TIMERPROC
       FONTENUMPROC             WNDENUMPROC
       GOBJENUMPROC
    For more information on C++ callbacks, please see the May 1993 issue of the "Windows Tech Journal." The following sample demonstrates how to use a static member function as a thread function, and pass in the "this" pointer as an argument. 
    Sample Code #include &lt;windows.h&gt;
    class A { public: 
       int x;
       int y;   A() { x = 0; y = 0; }   static StartRoutine( A * );   // Compiles clean, includes "this" pointer
    }; 
    void main( )

       A a;   DWORD dwThreadID;   CreateThread( NULL,
    0, (LPTHREAD_START_ROUTINE)(a.StartRoutine), &a, // Pass "this" pointer to static member fn 0, &dwThreadID 
       );

      

  2.   

    lResult = (this->*mmf.pfn_is)((LPTSTR)lParam)
    mmf.pfn_is是指向消息响应函数的指针,存储函数地址。this是响应消息的对象。使用(this->*mmf.pfn_is)()其实就是详细响应函数的调用。我想是不是您的消息入口啊之类的搞错了,以致mmf.pfn_is指向一个不存在的函数。你查看一下pfn_is变量。
    应该不是mfc的问题。是编程者没有正确使用mfc的问题。
      

  3.   

    CCreateContext cc;
    cc.m_pNewViewClass = RUNTIME_CLASS(C_AlamView);
    cc.m_pCurrentDoc = NULL;
    cc.m_pNewDocTemplate = NULL;
    cc.m_pLastView = NULL;
    cc.m_pCurrentFrame = NULL; m_pView = (C_AlamView*)CreateNewView(&cc, this, CRect(0, 0, 0, 0), 0);///CreateNewView函数:
    CWnd* CreateNewView(CCreateContext* pContext, CWnd *pParent, CRect& rect, int wID)
    {
    CWnd* pWnd = NULL;

    if (pContext != NULL)
    {
    if (pContext->m_pNewViewClass != NULL)
    {
    pWnd = (CWnd*)pContext->m_pNewViewClass->CreateObject();
    if (pWnd == NULL)
    {
    TRACE1("Error: Dynamic create of view %Fs failed\n", pContext->m_pNewViewClass->m_lpszClassName);
    return NULL;
    }
    ASSERT(pWnd->IsKindOf(RUNTIME_CLASS(CWnd)));

    if (!pWnd->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, rect, pParent, wID, pContext))
    {
    TRACE0("Error: couldn't create view \n");
    return NULL;
    }
    // send initial notification message
    pWnd->SendMessage(WM_INITIALUPDATE);
    }
    }
    return pWnd;
    }
      

  4.   

    上面的代码中,我创建了一个视图,就导致了 lResult = (this->*mmf.pfn_is)((LPTSTR)lParam)的异常,请帮助我看看,问题在哪儿?
      

  5.   

    在Create和SendMessage处加断点,看哪个消息导致错误。
    是不是doc为NULL的问题?