我有一个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'更优雅?
答案 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>