成员函数指针和继承 [英] member function pointers and inheritance

查看:135
本文介绍了成员函数指针和继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在开发一个简单的win32封装为了我自己的方便,我遇到了一个稍微复杂的问题。



这有很多其他成员,但我略去了一点,只剩下讨厌的成员。

  class Windows :: AbstractWindow 
{
public:
void InstallHandler(UINT msgName,void(Windows :: AbstractWindow :: *)(HWND,UINT,WPARAM,LPARAM)

private:
std :: map< UINT,void(Windows :: AbstractWindow :: *)(HWND,UINT,WPARAM,LPARAM) HandlerIndex;

};

(对于记录,Windows在这种情况下是一个命名空间的各种类和对象)



只是有点讨厌,但lemme解释我的过程和推理。我有一个名为AbstractWindow的类,它包含了一个非常面向对象方式的窗口的所有功能的大部分。



我现在正在开发一种获取私有成员函数的方法,并通过指向它们的指针将它们存储在地图中,这些函数由Windows消息标识应该处理。这样,当Windows过程接收到消息时,它会挖掘此映射以查看是否已为其安装了处理程序。如果它有它调用该函数并退出。它没有它调用DefWindowProc和退出。很容易。



但是,这个对象从来不应该被实例化,只是应该继承和扩展。问题是,map的函数指针declaraction是类型AbstractWindow,这将不允许我存储从AbstractWindow继承的类型的成员函数指针。例如,

  class BasicWindow:public Windows :: AbstractWindow 
{
public:
BasicWindow()
{
InstallHandler(WM_CREATE,& create);
}

private:
void创建(HWND,UINT,WPARAM,LPARAM){}
}
pre>

...产生错误:

 错误C2664: 'Windows :: AbstractWindow :: InstallHandler':不能将参数2从'void(__thiscall BasicWindow :: *)(HWND,MSG,WPARAM,LPARAM)'转换为'void(__thiscall Windows :: AbstractWindow :: * UINT,WPARAM,LPARAM)'

,因为指针类型不一样,基类。那么,任何人都希望建议一个解决方案,同时仍然保持这种方法?

解决方案

您可以使用这种方式应该阅读好奇的重复模板模式( http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)。



基本上,你把你的基类转换成带有指定子类的模板参数的模板。



也许如果你看到它会更容易理解:

 命名空间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){}
};


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 omitting a bit and leaving just the offending members.

class Windows::AbstractWindow
{
public:
     void InstallHandler(UINT msgName, void (Windows::AbstractWindow::*)(HWND, UINT, WPARAM, LPARAM));

private:
     std::map<UINT, void (Windows::AbstractWindow::*)(HWND, UINT, WPARAM, LPARAM)> HandlerIndex;

};

(for the record, Windows in this case is a namespace of various classes and objects i've made)

just a bit nasty but lemme explain my process and reasoning. i have a made a class called AbstractWindow which contains most of all of the functionality of a window in a very object oriented way.

I'm now working on a method of taking private member functions, and storing them in a map via pointers to them, which are identified by the Windows message that they are supposed to handle. This way, when a message is received by the windows procedure, it digs through this map to see if you've installed a handler for it. If it has it calls that function and exits. It it hasn't it calls DefWindowProc and exits. easy enough.

However, this object is never supposed to be instantiated and is simply supposed to be inherited from and extended. problem is, that map's function pointer declaraction is of type AbstractWindow which will not allow me to store member function pointers of a type inherited from AbstractWindow. For example,

class BasicWindow : public Windows::AbstractWindow
{
public:
    BasicWindow() 
    {
         InstallHandler(WM_CREATE, &create);
    }

private:
    void Create(HWND, UINT, WPARAM, LPARAM) {}
}

... yields an error:

error C2664: 'Windows::AbstractWindow::InstallHandler' : cannot convert parameter 2 from 'void (__thiscall BasicWindow::* )(HWND,MSG,WPARAM,LPARAM)' to 'void (__thiscall Windows::AbstractWindow::* )(HWND,UINT,WPARAM,LPARAM)'

because the pointer types are not the same, despite being inherited from the base class. So does anyone wish to suggest a solution while still maintaining this method? And if not, i'm also open to suggestions that you think would make message handling more convenient than this way.

解决方案

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) {}
};

这篇关于成员函数指针和继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆