【问题标题】:Is Windows API an object-oriented framework?Windows API 是面向对象的框架吗?
【发布时间】:2018-07-17 19:07:46
【问题描述】:

在Windows API中创建控件对象(HWND)时,不允许直接访问控件对象的成员,只能通过特定函数访问,这是OOP的一个特点。

另外,Windows API 支持多态,例如我可以有以下功能:

void setHwndText(HWND hwnd)
{
    SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)"Hello World");
}

上述函数可以改变多种对象的文本,而不仅仅是一种类型,例如它可以改变窗口的标题、编辑控件的文本和按钮控件的标题。

我不知道 Windows API 是否支持继承,但即使不支持,我认为 OOP 中继承的主要目的是允许多态性,正如我所展示的那样,Windows API 确实支持。

这是否意味着可以将 Windows API 视为面向对象的框架?

【问题讨论】:

  • Windows API 不是框架。这是一个 API。除此之外,您会看到许多用 C 实现的 OOP 范例。还有继承(例如,注册一个窗口类,将消息委托给基类实现 DefWindowProc)。不过,这个问题不太适合 Stack Overflow。
  • This 讨论这个话题。
  • @IInspectable 尽管在传统的面向对象框架中,您不会为每个实例注册一个函数指针来实现成员函数;您将声明一个假设的class UrWindow 的子类,它会覆盖虚拟成员回调函数。
  • Windows API 中也有很多 COM。 COM 立即支持封装、专业化和多态性。 @Davislor:你不能在 C 中这样做。在 C 中,注册函数指针是实现自定义行为的常用方法。
  • @IInspectable 早在 90 年代中期,当我在 Modula-2 中写作时,我会称之为“基于对象,但不是面向对象”。

标签: c oop winapi


【解决方案1】:

Windows 中的文件和窗口句柄类似于流、Unix 中的文件描述符、C 标准库中的FILE 指针等等。将不透明句柄传递给库函数和使用隐式 this 指针调用成员函数之间存在相似之处。

另一个更接近的例子是您使用RegisterClassEx() 注册的窗口类。这是句柄式 API 和 COM 之类的框架之间的过渡,每个人都同意它是“面向对象的”:您注册一个包含函数指针的结构,这很像虚函数表中的成员函数指针。您没有任何类型的类层次结构或要实现的接口选择。您没有覆盖默认实现,或者在覆盖其他方法时继承某些方法。你只是传递了一个包含函数指针的结构。

区别可能会变得模糊。如果你看一下 Nicholas Wirth 设计的语言家族,Pascal 是一种受 Algol 启发的传统结构化命令式语言,而 Modula、Modula-2 和 Oberon 在面向对象的方向上实验性地发展。当时,这些中间语言被称为“基于对象的”。到 90 年代中期,Delphi 和 Object Pascal 等语言适合面向对象的范式。

但是,类似于 70 年代后期的库通常不被称为“面向对象”。特别是,它们没有继承的类层次结构。客户端应用程序本身也不管理实例,它们会自动创建和销毁以防止内存泄漏。

当 C API 执行类似于多态性和继承的事情时,例如能够提供指向回调函数的指针,它以不同的方式执行。在传统的面向对象语言中,您将静态定义覆盖虚拟成员函数的窗口的派生类,而不提供任意函数指针来回调(尽管与面向对象的访问者模式有一些相似之处)。

类似名称的“窗口类”之类的只是回调。尽管多态对象的所有实现都建立在包含函数指针的结构之上,但并非所有使用回调函数的程序都是面向对象的。一个更接近面向对象编程的例子是 Winsock 2 如何使套接字描述符成为一种特殊类型的文件描述符,可以将其传递给内核文件函数(使用强制转换)。如果我们有一个面向对象的 API,将成员函数重命名为全局函数,将隐式 this 指针作为显式参数,然后将其转换为不透明的句柄,它仍然主要是面向对象的。它唯一会失去的是静态类型安全和封装。更类似于 OOP,我肯定会称之为 OOP,是组件对象模型及其继承者,其中对象实现接口。

已经有几个“面向对象”的 Windows API,包括 Microsoft 基础类、Borland 的对象 Windows 库、对象链接和嵌入、更新的组件对象模型和公共语言运行时库,甚至更新的 Windows 运行时。

【讨论】:

  • 调用 CLR "new" 有点牵强。它已经存在了将近 2 年。新的 API 称为 Windows Runtime,在更传统的意义上它是面向对象的。即使它仍然作为 C 接口公开。
  • @Davislor 当您在 Windows 世界中列出 OO API 时,COM 可能至少值得一提。
  • Winsock 套接字实际上是内核文件对象,通常在“\Device\Afd”上打开。您可以将它与 ReadFileWriteFile 一起使用,但在某些情况下,这可能会降低性能。
  • 关于内核句柄,执行者的对象管理器实现了一个类型系统。内核对象是对象类型(例如文件、进程、事件、作业)的实例,而这些对象类型又是“类型”元类型的实例。可用的属性和过程(方法)是固定的。每种类型还与系统调用相关联,以查询和设置一组可扩展的信息和行为(例如NtQueryInformationFileNtSetInformationFile),但无法对类型进行子类化和扩展。
  • @eryksun The MS documentation says, “在 Winsock 应用程序中,套接字描述符不是文件描述符,必须与 Winsock 函数一起使用。” Winsock2 不同。所以,Winsock 有一个closesocket() 函数,Winsock2 可以只使用它来处理文件。
猜你喜欢
  • 2016-12-06
  • 2011-04-11
  • 2011-03-26
  • 2010-09-11
  • 1970-01-01
  • 2018-10-28
  • 2014-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多