Thread: Pointers to member functions...

  1. #1
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587

    Pointers to member functions...

    Code:
    class Window{
        public:
            Message Msg;
    
            Window(HINSTANCE hInstance,
                    LPSTR lpstrTitle,
                    HWND hwndParent,
                    HBRUSH hbrBackground,
                    DWORD dwStyle,
                    DWORD dwExStyle,
                    int width,
                    int height,
                    int x,
                    int y);
        private:
            LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
    };
    I want to "wincl.lpfnWndProc = &WindowProcedue", but I'm getting really complicated errors that I kinda understand. They seem to say what I'm doing is forbidden, is there another way to do it?(I Googled, found this: [33] Pointers to member functions ..Updated!.., C++ FAQ Lite, but I really don't like that solution. )

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    There is no easy solution to that one (if there were a general solution to a callback function that takes N arguments, I'd love to hear it).
    You simply have to do what the link says. Blame C for that.
    The reason is that the member functions are coupled to an instance. So if you pass a pointer to your member function, which instance of the function will it call?

    Btw, I have also implemented a simple Window class. You may have a look at it and expand on it if you wish:
    Code:
    #ifndef WINDOWS_H_20100708_1707
    #define WINDOWS_H_20100708_1707
    
    #include <Windows.h>
    #include "GetInstance.h"
    #include <assert.h>
    #include <boost/thread.hpp>
    
    namespace Stuff
    {
    	namespace Window
    	{
    		typedef LRESULT (CALLBACK WndProc_t)(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    		class CWindow
    		{
    		protected:
    			HWND m_hWnd;
    
    		public:
    			// WndProc is a pointer to WndProc procedure. MUST call CWindow::WindowProc!
    			void Initialize(WndProc_t* WndProc)
    			{
    				// TODO: Place code here.
    				WNDCLASSEXW wcex = {};
    
    				wcex.cbSize = sizeof(WNDCLASSEX);
    
    				wcex.style			= CS_HREDRAW | CS_VREDRAW;
    				wcex.lpfnWndProc	= WndProc;
    				wcex.cbClsExtra		= 0;
    				wcex.cbWndExtra		= 0;
    				wcex.hInstance		= Stuff::Handle::GetAppInstance();
    				wcex.hIcon			= 0;
    				wcex.hCursor		= 0;
    				wcex.hbrBackground	= 0;
    				wcex.lpszMenuName	= nullptr;
    				wcex.lpszClassName	= L"Callback window";
    				wcex.hIconSm		= 0;
    
    				assert(RegisterClassExW(&wcex));
    				// Perform application initialization:
    
    				m_hWnd = CreateWindowW(L"Callback window", L"", WS_OVERLAPPEDWINDOW,
    					CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, Stuff::Handle::GetAppInstance(), nullptr);
    
    				assert(m_hWnd);
    
    				// Main message loop:
    				boost::thread(&CWindow::MessageLoop, this);
    			}
    
    		protected:
    			void MessageLoop()
    			{
    				MSG msg;
    				while (GetMessage(&msg, nullptr, 0, 0))
    				{
    					TranslateMessage(&msg);
    					DispatchMessage(&msg);
    				}
    			}
    
    		public:
    			LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    			{
    				switch (message)
    				{
    					case WM_DESTROY:
    						PostQuitMessage(0);
    						break;
    					default:
    						return DefWindowProc(hWnd, message, wParam, lParam);
    				}
    				return 0;
    			}
    
    			~CWindow() { DestroyWindow(m_hWnd); }
    
    			HWND GetHwnd() { return m_hWnd; }
    		};
    	}
    }
    
    #endif
    Last edited by Elysia; 08-17-2010 at 11:25 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587
    > (if there were a general solution to a callback function that takes N arguments, I'd love to hear it)
    Huh? What are you talking about?

    It works now. I just added static and it compiled.

    P.S. You really need to change your avatar back. Every time I see it, with your name, it confuses me.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What I mean is this:
    Consider a slew of functions, F1 ... Fn whose callback functions takes only one parameter - void*. Essentially they forward this argument to their callback functions. We could then generalize this to:
    Code:
    template<typename T> struct SCallback
    {
        T Functor;
    }
    
    template<typename T> SCallback<T>* make_callback(T Functor)
    {
        return new SCallback<T>(Functor);
    }
    
    template<typename T> void Callback(void* arg)
    {
        T* pArg = static_cast<T*>(arg);
        pArg->Functor();
        delete pArg;
    }
    
    class foo
    {
        void bar1() 
        {
            auto pArgs = make_callback([]() { this->MyCallback() }) );
            F1(&Callback<decltype(pArgs)>, pArgs);
        }
        // ...
        void barN() 
        {
            auto pArgs = make_callback([]() { this->MyCallback() }) );
            FN(&Callback<decltype(pArgs)>, pArgs);
        }
    
        void MyCallback();
    };
    I use one function as a callback function to ALL the functions F1 ... FN by passing a simple argument. Saves a function for each callback.

    But what if the callback functions for F1 .. FN doesn't take 1 parameter? They this solution won't work.

    And no, I like this new avatar The old was one was getting old.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by Elysia View Post
    Btw, I have also implemented a simple Window class. You may have a look at it and expand on it if you wish:
    It'll need fixing before it gets expanded upon. For starters, writing effectual code in an assert is just wrong; the message pump has to run in the same thread the window was created on; and CloseWindow only minimizes the window, you want DestroyWindow. You're also missing the intervening * between the calling convention and the name in your Wndproc_t typedef.

  6. #6
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    the message pump has to run in the same thread the window was created on
    No, it doesn't. It is possible to separate them. It just isn't worth while.

    That said, he isn't doing that; what he is doing will probably fail. He should be doing what you said.

    You're also missing the intervening * between the calling convention and the name in your Wndproc_t typedef.
    Not really, look at the way he is using the `typedef'.

    Soma

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by adeyblue View Post
    It'll need fixing before it gets expanded upon.
    Aye, it is by no means perfect, and I'm not that good on Windows stuff. I usually just use a framework. But for times when I can't/don't want to use MFC, we have to do it the old fashioned way.
    So without further ado, I shall comment upon, reflect and fix the feedback.

    For starters, writing effectual code in an assert is just wrong;
    I am not sure what you mean. Just putting an assert(hWnd) is a bad idea, certainly. I am aware of that. Ideally it would throw an exception if it fails, but I haven't implemented any exception handling in the class really because it's still unfinished and so few components still use it, so I can get away with it.

    the message pump has to run in the same thread the window was created on;
    May you consider expanding upon the why? I don't claim it works perfectly or is right, but at least right now it works (but we all know that work is not the same as right).

    and CloseWindow only minimizes the window, you want DestroyWindow.
    Good point. I've fixed that locally. Thanks.

    You're also missing the intervening * between the calling convention and the name in your Wndproc_t typedef.
    And I didn't, as Soma pointed out. It's a function type, not a function pointer type. So I create a pointer to the type, hence a function pointer. Nifty and easily more readable IMO.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    I am not sure what you mean. Just putting an assert(hWnd) is a bad idea, certainly. I am aware of that. Ideally it would throw an exception if it fails, but I haven't implemented any exception handling in the class really because it's still unfinished and so few components still use it, so I can get away with it.
    asserts with side effects are bad because if you disable asserts, the expression won't be run at all.

    assert(hWnd) is fine, but not assert(RegisterClassExW(&wcex)), assuming RegisterClassExW does something.

    Code:
    int rtn = RegisterClassExW(&wcex);
    
    assert(rtn && "Some error message");
    seems to be pretty standard.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yeah, I'm aware of that. I could put the whole create window in an assert, but didn't for the outlined reasons.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointers to member functions - quick Q
    By Stonehambey in forum C++ Programming
    Replies: 18
    Last Post: 09-01-2008, 11:30 AM
  2. Modules and Member Functions
    By arrgh in forum C++ Programming
    Replies: 2
    Last Post: 05-07-2008, 02:46 AM
  3. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 06:58 PM
  4. Replies: 4
    Last Post: 11-23-2003, 07:15 AM
  5. Borland, libraries, and template member functions
    By roktsyntst in forum C++ Programming
    Replies: 0
    Last Post: 06-01-2003, 09:52 PM