member function pointers and inheritance

前端 未结 3 1202
南方客
南方客 2021-01-14 04:51

So i\'m working on a simple win32 wrapper for my own convenience, and i\'ve run into a slightly complicated problem.

this has alot of other members, but i\'m omittin

相关标签:
3条回答
  • 2021-01-14 05:16

    You should read up on the Curiously Recurring Template Pattern (http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).

    Basically, you turn your base class into a template with a template parameter that specifies the sub-class.

    Perhaps it'll be easier to understand if you see it:

    namespace Windows
    {
         template <typename T>
         class AbstractWindow
         {
         public:
              void InstallHandler(UINT msgName, void (T::*)(HWND, UINT, WPARAM, LPARAM));
    
         private:
              std::map<UINT, void (T::*)(HWND, UINT, WPARAM, LPARAM)> HandlerIndex;
    
         };
    }
    
    class BasicWindow : public Windows::AbstractWindow< BasicWindow >
    {
    public:
        BasicWindow() 
        {
             InstallHandler(WM_CREATE, &BasicWindow::Create);
        }
    
    private:
        void Create(HWND, UINT, WPARAM, LPARAM) {}
    };
    
    0 讨论(0)
  • 2021-01-14 05:20

    The problem you are facing is you are trying to do the conversion in the opposite way. Function pointers are contravariant in their this arguments (ie. a function pointer to a base class' function will do for a function pointer to a derived class' method, not vice versa). You can:

    • just cast (with static_cast, as it is the converse of an implicit conversion). It will work fine as long as you can ensure that you never ever call the method on an inappropriate class (eg. NotABasicWindow().*method()).
    • get rid of the scheme, and register general functions (ie. anything that can be called instead of member function pointers). You would use eg. std::function<void(HWND, UINT, WPARAM, LPARAM)> as your handler type and registers handlers that would know their window (eg. lambda functions).

      • lambda functions are a feature of C++11. They roughly correspond to function objects with binders; they create an anonymous function that can reference variables from the scope in which they are. An example would be

        [=](HWND wnd, UINT i, WPARAM wp, LPARAM lp) { this->printHandler(wnd, i, wp, lp); }
        

        which would remember this, so it would call printHandler for the current object (current of the code creating a lambda, not invoking code) when called. Of course, the object on which the method should be invoked could be just another parameter.

        Lambdas, as well as other function objects (ie. objects that have operator() defined) can be converted to and stored as std::function objects.

    0 讨论(0)
  • 2021-01-14 05:31

    Does something of this nature will work...? Ps. I'd used a typedef for the function signature.

    BasicWindow() 
        {
             InstallHandler(WM_CREATE, reinterpret_cast<void (__thiscall Windows::AbstractWindow::* )(HWND,UINT,WPARAM,LPARAM)>(&create));
        }
    
    0 讨论(0)
提交回复
热议问题