静态函数内的非静态参数

Posted

技术标签:

【中文标题】静态函数内的非静态参数【英文标题】:Non-static parameter inside a static function 【发布时间】:2012-04-05 16:08:09 【问题描述】:

我在 MyClass 中有这个静态回调函数,我尝试从中调用另一个静态函数。但是有一个问题,Register() 采用的参数之一是非静态类变量。

我曾想过使用“this”关键字来解决这个问题,但似乎我做不到(“this”:只能在非静态成员函数中引用)。这是我的代码:

class MyClass

...
    static LRESULT CALLBACK klHkProc(int nCode, WPARAM wParam, LPARAM lParam);
    static BOOL Register(DWORD vKey,KEYBLOCK* ptrKEYBLOCK);
    KEYBLOCK *kb;       
...


LRESULT CALLBACK MyClass::klHkProc(int nCode, WPARAM wParam, LPARAM lParam)

    PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) (lParam);
    if (wParam == WM_KEYDOWN) 
    
        MyClass::Register(p->vkCode,this->kb);
    
    return CallNextHookEx(NULL, nCode, wParam, lParam);

有什么建议吗?

【问题讨论】:

静态函数不能访问实例成员。您想从哪里获取实例? 您是否有地方可以将额外数据传递到您注册回调的地方?如果是这样,您可以在那里传递this 【参考方案1】:

鉴于您写的内容,如果没有更多信息,很难回答这个问题。

但是,假设应该处理MyClass 的所有实例,我建议添加一个static std::list<MyClass *>,将每个实例的this 指针放入MyClass 的构造函数中,然后放入MyClass 的析构函数中从该列表中删除 this

然后在您的静态 klHkProc() 中,您将遍历 MyClass 的所有实例的静态列表,并为每个调用 MyClass::Register() 使用每个此类注册的 MyClass 实例的 kb

这是执行此操作的代码的粗略大纲:

class MyClass

...
public:
    static LRESULT CALLBACK klHkProc(int nCode, WPARAM wParam, LPARAM lParam);
    static BOOL Register(DWORD vKey,KEYBLOCK* ptrKEYBLOCK);
    static std::list<MyClass *> allInstances;
    KEYBLOCK *kb;

    MyClass() 
      ...
      allInstances.push_back(this);
      ...
    
    ~MyClass() 
      ...
      // Assumes not a huge list of instances as this is O(n) and thus destruction
      // of all instances of MyClass in O(n^2) on the number of instances.
      allInstances.remove(this);
      ...
    

...
;

LRESULT CALLBACK MyClass::klHkProc(int nCode, WPARAM wParam, LPARAM lParam)

    PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) (lParam);
    if (wParam == WM_KEYDOWN)
    
        std::list<MyClass *> itr = allInstances.begin();
        std::list<MyClass *> end = allInstances.end();
        for (; itr != end; ++itr) 
          MyClass *current = *itr;
          MyClass::Register(p->vkCode, current->kb);
        
    
    return CallNextHookEx(NULL, nCode, wParam, lParam);

【讨论】:

类的每个实例都有一个指向当前 KeyBlock 对象的指针,每个实例都需要不同,因为每个实例使用不同的键块。我想使用Register函数将按键记录到特定实例的KeyBlock对象中 所以这是来自用户的按键事件,并且在每个按键事件时您希望采取注册操作? 你怎么知道MyClass的哪个实例应该是keypress事件的目标?另外,在按键上是 klHkProc() 被调用还是正在对注册的项目进行某些操作? 我让每个类都创建自己的线程并同时捕获击键,所以基本上是所有实例。 klHkProc 是通过 SetWindowsHookEx 设置的 我是否正确理解您的应用程序中的所有线程都应该处理每个击键事件。【参考方案2】:

静态成员和任何特定对象实例之间没有隐式连接。

您可以将指向MyClass 对象的指针或引用传递给klHkProc(),然后它可以将其传递给Register()

【讨论】:

【参考方案3】:

一般来说,如果 KEYBLOCK *kb 不是静态的,则不能在静态函数中引用它。 'this' 指针仅在对象实例中才有意义。因此,如果 KEYBLOCK *kb 仅在实例化对象中有意义,那么您将必须在 Register 或 klHkProc 中实例化 MyClass。如果您向我们提供了关于 Register 应该做什么的更好的上下文,而不仅仅是显示调用者,那么确定后者在 Register 中实例化 MyClass 是否有意义会更容易。

【讨论】:

以上是关于静态函数内的非静态参数的主要内容,如果未能解决你的问题,请参考以下文章

MFC中静态成员函数调用其他类的非静态变量

调用 UIViewController 类的非静态函数

指向任何类类型的非静态成员函数的 C++ 函数指针

在 C++ 成员函数中使用“静态”关键字限制访问

C++中得sort函数的比较函数(第三个参数)为什么要声明为static

从嵌套类的函数访问父级的非静态成员