【发布时间】:2010-02-25 15:04:08
【问题描述】:
这对你们中的一些人来说可能是一个愚蠢的问题,也许我问错了这个问题,因为我是 C++ 新手。但是我注意到,在很多 Win32 应用程序中工作时,您会使用大量的指针资源。为什么你必须总是获取一个对象指针?为什么不启动该类的新实例。说到这一点,我注意到在大多数情况下,您从不启动新对象,而是总是调用返回该指针的方法。如果该指针正在其他地方使用怎么办。如果您更改该指针并且它正在其他地方使用,您不会搞砸一些事情吗?
【问题讨论】:
这对你们中的一些人来说可能是一个愚蠢的问题,也许我问错了这个问题,因为我是 C++ 新手。但是我注意到,在很多 Win32 应用程序中工作时,您会使用大量的指针资源。为什么你必须总是获取一个对象指针?为什么不启动该类的新实例。说到这一点,我注意到在大多数情况下,您从不启动新对象,而是总是调用返回该指针的方法。如果该指针正在其他地方使用怎么办。如果您更改该指针并且它正在其他地方使用,您不会搞砸一些事情吗?
【问题讨论】:
Windows API 是为 C 设计的,它曾经是并且仍然是系统编程中最常用的语言; C API 是系统 API 的事实上的标准,为此几乎所有其他语言都有并且有一些方法可以调用外部 C 函数,因此编写 C API 有助于与其他语言兼容。
C API 只需要一个简单的 ABI,它几乎只包含用于函数的调用约定的定义(以及一些关于结构布局的内容)。相反,C++ 和其他面向对象的语言需要一个复杂的 ABI,它必须定义对象在内存中的布局方式、如何处理继承、如何布局 vtable、如何传播异常、将 RTTI 数据放在哪里, ...此外,并非所有语言都是面向对象的,并且将 C++ 的 API 与其他非面向对象的语言一起使用可能会很痛苦(如果你曾经使用 C 中的 COM,你就会明白我的意思)。
顺便说一句,在最初设计 Windows 时,C++ 在 PC 上并没有那么普遍,而且 C 也没有这么大量使用:实际上,Windows 3.11 的很大一部分和许多应用程序都是仍然是用汇编写的,因为那个时代的内存和 CPU 限制非常严格;编译器也没有现在那么聪明,尤其是 C++ 的。在手工组装通常是唯一解决方案的机器上,C++ 开销确实是不可接受的。
对于指针的事情:Windows API 几乎总是使用句柄,即不透明的指针,以便能够在不影响现有应用程序的情况下更改每个资源的底层性质并阻止应用程序乱用内部结构。窗口管理器用来表示内部窗口的结构是否改变并不重要:所有应用程序都只使用一个 HWND,它总是指针大小。您可能会认为这是某种 PIMPL 习语。
但是,Windows 在某种程度上是面向对象的(例如,参见整个“窗口类”概念,或者更深层次的 NT 内核的内部工作,它在很大程度上基于“对象”概念),但是它最基本的 API,作为简单的 C 函数,以某种方式隐藏了这种面向对象的性质。另一方面,多年后设计的 shell 主要是用 C++ 编写的,它提供了一个真正面向对象的 COM 接口。
有趣的是,您可以在 COM 中看到在构建跨语言但仍偏向 C++ 的面向对象接口时必须面对的所有权衡:结果相当复杂,在某些方面很难看,而且使用起来并不简单语言。相反,Windows API 作为简单的函数通常更容易调用。
如果您对基于 C++ API 的系统感兴趣,可以查看Haiku;就个人而言,这是我对该项目非常感兴趣的方面之一。
顺便说一句,如果你打算只使用 API 进行 Win32 编程,你最好找一本好书来习惯这些“特殊性”和其他 Win32 习语。两个著名的是Rector-Newcomer 和Petzhold。
【讨论】:
因为 Win32 Api 是用纯 C 编写的,而不是 C++。因此,几乎任何语言的任何程序都可以调用这些 API。
另外,没有简单的机制可以跨不同的模块和不同的语言使用对象。 IE。你不能将 C++ 类导出到 python。当然,也有像 OLE/COM 这样的技术,但它们仍然是用纯 C 编写的。而且使用起来有点复杂。
另一方面,对普通 C 函数的调用是标准化的。因此,您可以使用任何语言从 DLL 或静态库中调用例程。
【讨论】:
Win32 被设计为使用 C 语言而不是 C++。
这就是为什么您会看到已定义的 BOOL 而不是 bool 的返回类型。bool 特定于 C++,在 C 中不存在。
有关 Microsoft 面向对象的 Win32 包装器,请参阅MFC。
从那时起,微软推出了一个较新的框架,即 .Net Framework。
.Net 框架虽然基于托管代码,但并不本机运行。在 Windows 上进行 GUI 编程的最现代方法是 WPF 甚至 Silverlight。
进行非托管 GUI 编程的最现代方式仍然是使用 MFC,尽管有些人仍然更喜欢直接使用 Win32。
注意使用指针并不是 C 特有的,它在 C++ 中仍然很常见。
【讨论】:
第一个原因是因为传递指针很便宜。指针在 x86 上为 4 个字节,在 x64 上为 8 个字节。虽然它指向的结构或类可以占用更多的内存。所以实例化一个类意味着一次又一次地保留新的内存。从速度和内存消耗 POV 来看,这效率不高。
另一种方法是传递对对象或智能指针或类似结构的引用。但是win32 api是在C时代设计的,所以到现在为止;)
关于指针的潜在混乱 - 当然有可能。但大多数情况下,它们的生命周期都在 API 中明确说明(如果不明显的话)。
【讨论】:
可能是因为 Win32 API 比主流的面向对象编程“更老”,它的核心不是 C++ API。
【讨论】:
这几乎就像您应该尝试许多 OO 包装器之一。像 MFC 或 .net。
【讨论】:
Windows API 是普通的旧 C,因此到处都使用指针。此外,您要求 Windows 提供新指针的原因是因为 Windows 需要跟踪所有对象......它分配事物并告诉您一个指针(或有时只是一个数字 ID)让您使用它们。
【讨论】:
所有的 HWND、HANDLE、HDC 都只是一个弱的尝试来制作钳制的、类似对象的数据类型(使用struct)。 C FAQ 对此有疑问 -> http://c-faq.com/struct/oop.html.
【讨论】:
要了解您可能想要阅读的指针the CPlusPlus.com tutorial on pointers。
【讨论】: