win32应用程序不是那么面向对象,为什么有这么多指针?

2024-01-11

对于你们中的一些人来说,这可能是一个愚蠢的问题,也许我问这个问题是错误的,因为我是 C++ 新手。但我注意到,在许多 Win32 应用程序中工作时,您会使用大量指针资源。为什么必须始终获取对象指针?为什么不启动该类的新实例。说到这一点,我注意到在大多数情况下,您从不启动新对象,但总是调用返回该指针的方法。如果该指针在其他地方使用怎么办?如果你改变了那个指针并且它正在其他地方使用,你不会把事情搞砸吗?


Windows API 是为 C 语言设计的,C 语言曾经并且仍然是最常用的系统编程语言; C API 是系统 API 的事实上的标准,为此,几乎所有其他语言都拥有并且有某种方法来调用外部 C 函数,因此编写 C API 有助于与其他语言兼容。

C API 只需要一个简单的 ABI,它几乎只包含用于函数的调用约定的定义(以及有关结构布局的内容)。相反,C++ 和其他面向对象的语言需要复杂的 ABI,必须定义对象如何在内存中布局、如何处理继承、如何布局 vtable、如何传播异常、在哪里放置 RTTI 数据、 ...此外,并非所有语言都是面向对象的,并且将 C++ 的 API 与其他非面向对象的语言一起使用可能会很痛苦(如果您曾经使用过 C 中的 COM,您就知道我的意思)。

顺便说一句,当 Windows 最初设计时,C++ 在 PC 上还没有那么普及,而且 C 也没有被使用somuch:实际上,Windows 3.11的很大一部分和很多应用程序仍然是用汇编语言编写的,因为当时的内存和CPU限制非常严格;编译器也没有现在聪明,尤其是 C++ 编译器。在手工锻造组装通常是唯一解决方案的机器上,C++ 开销确实令人无法接受。

对于指针的事情:Windows API 几乎总是使用handles,即不透明指针,能够在不影响现有应用程序的情况下更改每个资源的底层性质,并阻止应用程序弄乱内部结构。窗口管理器用于在内部表示窗口的结构是否发生更改并不重要:所有应用程序都仅使用 HWND,它始终具有指针的大小。您可能认为这是某种 PIMPL 习惯用法。

然而,Windows 在某种程度上是面向对象的(例如,参见整个“窗口类”概念,或者,在更深层次上,NT 内核的内部工作,它很大程度上基于“对象”概念),但是它最基本的 API,即简单的 C 函数,以某种方式隐藏了这种面向对象的本质。另一方面,shell 是在多年后设计的,主要是用 C++ 编写的,它提供了一个真正面向对象的 COM 接口。

有趣的是,您可以在 COM 中看到在构建跨语言但仍然偏向 C++ 的面向对象接口时必须面对的所有权衡:结果相当复杂,在某些方面很难看,并且从任何语言使用都不是很简单。相反,Windows API 是简单的函数,通常更容易调用。

如果您对基于 C++ API 的系统感兴趣,您可以看看Haiku http://www.haiku-os.org/;就我个人而言,这是我对该项目非常感兴趣的方面之一。

顺便说一句,如果您打算仅使用 API 进行 Win32 编程,您最好读一本好书来习惯这些“特殊性”和其他 Win32 习惯用法。两个比较出名的就是新任校长 https://rads.stackoverflow.com/amzn/click/com/0201634929Petzhold http://www.charlespetzold.com/pw5/.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

win32应用程序不是那么面向对象,为什么有这么多指针? 的相关文章

  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • C++:无法使用scoped_allocator_adaptor传播polymorphic_allocator

    我有一个vector
  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 写入和读取文本文件 - C# Windows 通用平台应用程序 Windows 10

    有用 但在显示任何内容之前 您必须在文本框中输入内容 我想那是因为我使用了 TextChanged 事件处理程序 如果我希望它在没有用户交互的情况下显示文本文件的内容 我应该使用哪个事件处理程序 因此 我想在按下按钮时将一些数据写入 C W
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 将日期参数传递给对 MVC 操作的 ajax 调用的安全方法

    我有一个 MVC 操作 它的参数之一是DateTime如果我通过 17 07 2012 它会抛出一个异常 指出参数为空但不能有空值 但如果我通过01 07 2012它被解析为Jan 07 2012 我将日期传递给 ajax 调用DD MM
  • 作为字符串的动态属性名称

    使用 DocumentDB 创建新文档时 我想设置属性名称动态地 目前我设置SomeProperty 像这样 await client CreateDocumentAsync dbs db colls x new SomeProperty
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器

随机推荐

  • 在身份验证配置中找不到 Pod 执行角色或不具有所有必需的权限。我该如何调试?

    客观的 我希望能够使用 Fargate 部署 AWS EKS 我已经成功地进行了部署node group 然而 当我转而使用 Fargate 时 Pod 似乎都陷入了挂起状态 我当前的代码是什么样的 我正在使用 Terraform 进行配置
  • 在asp.net中发送邮件

    我正在使用 asp net 3 5 和 C 我想从 asp net 发送邮件 因为我从我的托管提供商处获得了一些详细信息 这些是 邮件 MySite net UserName Password 但我无法通过这些详细信息发送邮件 我在 web
  • Oracle TO_DATE 不工作

    我有这个查询不返回任何行 但有些记录的日期大于 90 年 6 月 25 日 为什么它不起作用 SELECT employee id last name hire date FROM employees WHERE hire date gt
  • C- SIGUSR1 在语法上到底是什么

    当我在kill 或signal 函数中使用SIGUSR1时 它在做什么 是宏吗 我读到它是用户定义的 但它是在哪里定义的 我可以制作 SIGUSR10 或以编程方式制作不同信号类型的 数组 吗 用户定义的信号意味着这些信号没有明确的含义 与
  • 使用 apache mod proxy 删除基本身份验证标头

    我有一个 HTTP Basic 安全网站 我用 mod proxy 隐藏了 Tomcat 应用程序服务器 我可以删除 HTTP Basic 标头吗 Tomcat应用程序读取标头并返回401未授权 不需要基本身份验证 因为应用程序使用 coo
  • 如何在 TypeORM 中模拟 EntityManager?

    我有以下代码从我的 NestJS 服务中模拟实体管理器 它在某种程度上有效 但问题在于指定什么findOne应该返回不同的实体 provide getEntityManagerToken useFactory connection Conn
  • R:根据数据框列表中的数据框名称设置列名称

    我有一个很大的数据框列表 如下所示 gt head lst Set1 ID Value 1 A 1 2 B 1 3 C 1 Set2 ID Value 1 A 1 2 D 1 3 E 1 Set3 ID Value 1 B 1 2 C 1
  • 自定义 sp_who 而不授予查看服务器状态

    我需要一个存储过程 可以将其提供给一组用户 使他们能够查看所有正在运行的进程 例如sp who 但我不希望这些用户拥有VIEW SERVER STATE权限 因为这会暴露太多元数据 我还需要允许用户终止进程 这是专门用于该组的开发服务器 我
  • Tinkerpop Gremlin 深度优先搜索顺序

    我有一个非常简单的示例图 我试图对其进行深度优先查询 假设图的边看起来像这样 A gt B A gt C B gt D B gt E C gt F C gt G 从 A 开始的深度优先搜索应该返回 A B D E C F G 但如果我能得到
  • 阻止 CTRL-Click 影响父数据网格

    我有一个 WPF DataGrid 它在 RowDetailsTemplate 中声明了另一个数据网格
  • 使用PIL在App Engine上绘制图像

    我已阅读主题 App Engine PIL 和叠加文本 https stackoverflow com questions 12695480 app engine pil and overlaying text 下面的代码将显示损坏的图像
  • 使用 TFLiteConverter 将 Keras 模型转换为量化的 tflite 版本会导致 NOTYPE 错误

    当转换和执行 keras 模型的 8 位量化时 我遇到了一个奇怪的错误 而图像数据集不会发生这种错误 import tensorflow python keras backend as K import tensorflow as tf f
  • 在向量上查找另一个特定数字之前的数字

    所以我想知道matlab中一个事件何时发生在另一个事件之前 我所说的事件是指数字 例如 我有一个向量 比方说 x 0 3 0 3 0 1 0 2 0 5 0 1 0 3 0 1 0 5 0 1 0 4 0 5 我想知道 0 1 发生在 0
  • 简化嵌套 Maybe 模式匹配

    我的代码中有以下构造 f Maybe A gt X f a case a of Nothing gt x Just b gt case b of Nothing gt y Just c gt case c of Nothing gt z J
  • SpringMVC Ajax 验证

    我有一个 Spring Mvc 3 表单 可以 POST 到控制器 在控制器中我调用来执行 DML 语句 我还有一个单独的验证类 它实现 Validator 并在我的控制器中调用 我在那里进行简单和复杂的验证 例如检查用户名是否存在并返回错
  • 如何在AFNetworking 2.0中获取下载进度?

    我正在使用 AFURLSessionManager 创建一个新的下载任务 AFURLSessionManager manager NSProgress p nil NSURLSessionDownloadTask downloadTask
  • 让 vim 分割窗口处于插入模式

    我想在 vim 分割窗口中查看 bash 命令的输出 split 为此 我安装了 Conque Shell 它在分割窗口中显示 bash ConqueTermSplit bash 然后我可以运行 shell 命令并在插入模式下观察输出 但是
  • 3 维空间中点与线之间的最短距离

    我试图使用 numpy 或 python 中的任何东西找到从点 x0 y0 z0 到由 x1 y1 z1 和 x2 y2 z2 连接的线的最小距离 不幸的是 我在网上能找到的所有内容都与二维空间有关 而且我对 python 还很陌生 任何帮
  • 在 Java 中如何确定另一个进程或可执行文件是 32 位还是 64 位

    Java 是否有任何可以调用的 API 可以知道进程或 exe 文件是 32 位还是 64 位 不是运行代码的 JVM 没有标准的 Java API 来确定是否external进程是 32 位或 64 位 如果您想执行此操作 则需要使用本机
  • win32应用程序不是那么面向对象,为什么有这么多指针?

    对于你们中的一些人来说 这可能是一个愚蠢的问题 也许我问这个问题是错误的 因为我是 C 新手 但我注意到 在许多 Win32 应用程序中工作时 您会使用大量指针资源 为什么必须始终获取对象指针 为什么不启动该类的新实例 说到这一点 我注意到