访问隐藏的'this'指针

时间:2010-04-14 16:22:35

标签: c++ event-handling callback this

我有一个GUI架构,其中元素触发事件如下:

guiManager->fireEvent(BUTTON_CLICKED, this);

每个被触发的事件都会传递'this'作为事件的调用者。从来没有时间我想要传递'this',而且,除了之外没有指向的'this'应该传递。

这给我带来了一个问题:我如何断言fireEvent永远不会被赋予除'this'之外的指针,我怎样才能简化(并均质化)对fireEvent的调用:

guiManager->fireEvent(BUTTON_CLICKED);

此时,当你写这样的东西时,我想起了一个相当常见的编译器错误:

class A {
public:
    void foo() {}
};

class B {
    void oops() { const A* a = new A; a->foo(); }
};

int main() {
    return 0;
}

编译它会给你

  

在会员功能中   'void B :: oops()':   错误:传球   'const A'作为'void'的'this'参数   A :: foo()'丢弃限定符

因为成员函数将'this'作为隐藏参数传递。

“啊!”我说。这(没有双关语)正是我想要的。如果我可以以某种方式访问​​隐藏的'this'指针,它将解决我之前提到的两个问题。问题是,据我所知你不能(可以吗?),如果可以的话,会有一些“但它会破坏封装!”除了我每次都已经传递'这个',所以它还能破坏它。

所以, 有一种方法来访问隐藏的'this',如果没有,是否有任何习惯用法或替代方法比每次传递'this'更优雅?

4 个答案:

答案 0 :(得分:6)

您可以定义

void Element::fireEvent(EVENT e) {
   guiManager->fireEvent(e, this);
}

每次为自己节省一些写作。您必须在某些点使用this进行调用,因为guiManager需要知道哪个Element调用了fireEvent。< / p>

答案 1 :(得分:1)

我不确定我是否理解你问题的后半部分(这里一次只做一件好事),但在以下情况下:

guiManager->fireEvent(BUTTON_CLICKED, this);

你可以从一个以guiManager作为参数的构造函数给这个类调用这个代码 - 称之为mGM。然后提供一个如下所示的成员函数:

void FireEvent( EventType e ) {
   mGM->fireEvent( e, this );
}
你打电话给:

FireEvent( BUTTON_CLICKED );

答案 2 :(得分:1)

取决于guiManager的范围。

你可以改写它:

class MyClass
{
public:

private:
  void FireEvent(GuiManager* guiManager, EventType e)
  {
    assert(guiManager);
    guiManager->FireEvent(e, this);
  }
};

是否有理由通过this(类型为MyClass*)而不是*this(类型为MyClass&)?如果你传递一个指针就意味着你希望该对象可能是NULL ......并且this永远不会为NULL(禁止对未定义行为的危险利用)

答案 3 :(得分:0)

另一种选择是创建一个#define宏,以便编译器为您添加“this”参数。它看起来像这样:

#define FIREEVENT(gm,e) gm->fireEvent(e, this)
FIREEVENT(guiManager, BUTTON_CLICKED); //compiles as: guiManager->fireEvent(BUTTON_CLICKED);

虽然,我不建议这样做,而且每当我看到C ++宏时,我都会感到畏缩,因为它们通常会使代码难以理解,并且可能导致编译错误。#/ p>