65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 代理和 Borland C++ Builder 事件处理 - 第一部分

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (6投票s)

2009年11月26日

CPOL

3分钟阅读

viewsIcon

26157

downloadIcon

259

描述了 Borland 如何通过 __closure 关键字绕过标准的 C++ 限制

引言

本文分为两个主要部分。

第一部分讨论标准的 C++ **成员函数指针 (MFP)**,它与普通函数指针不同。 它还说明了这些类型指针的限制,以及 Borland C++ Builder 如何通过其特殊的 MFP 类型 **__closure** 绕过这些限制。

第二部分展示了使用这种 MFP 的一个应用。 它详细解释了 Borland 如何使用他们自己的 MFP 类型来处理 Windows 事件,以及它与 MFC 风格或 Win32 API 风格相比有多么吸引人。

背景知识

我假设读者有足够的背景知识来使用 MFP。 我知道它的语法有点笨拙,但我没有详细解释。 相反,我使用注释来解释代码行的作用。
此外,我假设读者了解**继承**和**多态**。

第一部分 - 闭包:介绍

闭包是 C++ builder 中一个非常有用的特性。 为了说明这一点,我们首先来谈谈 C++ 中普通的成员函数指针。
尝试以下代码

#include <stdlib.h>
class Base{public:int baseFunc(int){}};
class Drvd:public Base{public:int drvdFunc(int){}};
class Alone{public:int aloneFunc(int){}};
//----------------------- Normal member-function-pointers ---------------
int main() {
    int (Base::*funcPtr)(int); 	// MFP of type Base::*
    funcPtr = &Drvd::baseFunc; 	// member-function pointed to
    Drvd ob; 			// type of calling object
    (ob.*funcPtr)(2); 		// calling of MFP is from here
    system("pause");
    return 0;
}

此代码展示了普通 C++ 成员函数指针 (MFP) 的行为。
正如我们所见,类型为 Base::* 的 MFP 可以指向以下内容

  • Base::baseFunc - 可以从 Base/Drvd 类型的对象调用。
  • Drvd::baseFunc - 可以从 Base/Drvd 类型的对象调用。
但不能指向以下内容
  • Drvd::drvdFunc
  • Alone::aloneFunc

如果我们将 MFP 的类型更改为 Drvd::*,情况将略有改变,可以指向

  • Base::baseFunc - 可以从 Drvd 类型的对象调用
  • Drvd::baseFunc - 可以从 Drvd 类型的对象调用
  • Drvd::drvdFunc - 可以从 Drvd 类型的对象调用

但是,它不能指向

  • Alone::aloneFunc

最后,如果我们的 MFP 类型为 Alone::*,它只能指向

  • Alone::aloneFunc - 可以从 Alone 类型的对象调用

并且它不能指向

  • Base::baseFunc
  • Drvd::baseFunc
  • Drvd::drvdFunc

Borland 的 "__closure" 关键字

Borland 向该语言添加了一个新的关键字,以绕过标准 C++ 设置的限制。
这个关键字是 __closure

到目前为止,我们有三个限制:

  • 类型为 Base 的 MFP 不能指向 Drvd 的新(未继承)成员函数。
  • MFP 不能指向继承层次结构之外的类中的任何成员函数,例如 Base/Drvd Alone
  • 我们不能使用对象名称将指针分配给我们的 MFP 中的成员函数,而必须使用完全限定的名称 Class::member-function。 如果解决了这个问题会非常有用,因为对象可能会在运行时发生多态变化。

实际上,第一个和第二个限制非常相似。 换句话说,我们的目标是使任何 MFP 指向任何类中的任何成员函数,无论该类是否在继承层次结构中。

让我们看看 Borland 如何使用 __closure 关键字解决这个问题。

#include <stdlib.h>
class Base{public:int baseFunc(int){}};
class Drvd:public Base{public:int drvdFunc(int){}};
class Alone{public:int aloneFunc(int){}};
//---------------------- Borland's C++ Buildre's Closures ---------------
int main() {
    int ( __closure *funcPtr)(int); 	// special MFP of type __closure
    Drvd ob;
    funcPtr = ob.drvdFunc; 		// member-function pointed to
    funcPtr(2); 			// calling of closure is from here
    system("pause");
    return 0;
}

尝试将 funcPtr 指向任何成员函数并查看结果。 只需确保它具有相同的参数列表和相同的返回类型。

现在让我们看看解决第三个问题会多么有用。 查看以下代码

#include <iostream.h>
class Base{public:virtual int baseFunc(int){cout << "i am baseFunc in Base class\n" ; }};
class Drvd:public Base{public:int baseFunc(int)
	{cout << "i am baseFunc in Drvd class\n" ; }};
//---------------------- Borland's C++ Buildre's Closures ---------------
int main() {
    int ( __closure *funcPtr)(int); 	// special MFP of type __closure
    Base *ob = new Base();
    funcPtr = ob->baseFunc; 	// member-function pointed to
    funcPtr(2); 			// calling of MFP is from here
    delete ob;
    ob = new Drvd(); 		// polymorphic behaviour
    funcPtr = ob->baseFunc;
    funcPtr(2);
    delete ob; ob=NULL;
    system("pause");
    return 0;
}

这不是很棒吗? 谢谢 Borland。

第二部分中再见。

历史

  • 2009 年 11 月 26 日:首次发布
© . All rights reserved.