我应该对不透明对象使用整数 ID 还是指针?

2023-12-20

我正在一些图形 API(DirectX9 和 DirectX11)之上编写一个抽象层,我想听听您的意见。

传统上,我会为每个我想要抽象的概念创建一个基类。
因此,在典型的 OO 方式中,我将拥有一个 Shader 类和 2 个子类 DX9Shader 和 DX11Shader。

我会重复纹理等的过程...当我需要实例化它们时,我有一个抽象工厂,它将根据当前的图形 API 返回适当的子类。
遵循 RAII,返回的指针将封装在 std::shared_ptr 中。

到目前为止一切顺利,但就我而言,这种方法存在一些问题:

  1. 我需要提出一个公共接口来封装这两个 API(以及未来的其他 API)的功能。
  2. 派生类存储在单独的 DLL 中(一个用于 DX9,一个用于 DX11 等...),并且在客户端中对它们拥有一个 Shared_ptr 是一种诅咒:在退出时,图形 DLL 会被卸载,并且如果客户端仍然有一个 Shared_ptr图形对象之一boom,由于从卸载的 DLL 调用代码而崩溃。

这促使我重新设计我的做事方式: 我以为我可以将原始指针返回到资源,然后让图形 API 清理干净,但仍然存在客户端悬空指针和接口问题。 我什至考虑过像 COM 这样的手动引用计数,但我认为这将是一种倒退(如果我错了,请纠正我,来自shared_ptr 世界,手动引用计数似乎很原始)。

然后我看到了 Humus 的工作,其中他的所有图形类都由整数 ID 表示(很像 OpenGL 所做的)。 创建一个新对象仅返回其整数ID,并在内部存储指针;一切都是完全不透明的!

代表抽象的类(例如 DX9Shader 等)都隐藏在设备 API 后面,这是唯一的接口。
如果想要设置纹理,只需调用 device->SetTexture(ID) 即可,其余的都在幕后发生。

缺点是 API 的隐藏部分过于臃肿,需要大量样板代码才能使其工作,而且我不喜欢全能类。

有什么想法/想法吗?


您说主要问题是 DLL 被卸载,但仍然有指向其内部的指针。出色地...不要那样做。你有一个类实例,它的成员是实施的在该 DLL 中。它从根本上来说是一个error只要这些类实例存在,该 DLL 就会被卸载。

因此,您需要对如何使用此抽象负责。正如你需要负责一样any从 DLL 加载的代码:在卸载 DLL 之前,必须清除来自 DLL 的内容。如何做到这一点取决于您。您可以有一个内部引用计数,该计数对于 DLL 返回的每个对象都会递增,并且仅在所有引用的对象消失后才卸载 DLL。或者任何东西,真的。

毕竟,即使您使用这些不透明的数字或其他什么,如果您在卸载 DLL 时对该数字调用这些 API 函数之一,会发生什么情况?哎呀...所以它并不能真正为您带来任何保护。无论哪种方式你都必须负责。

您可能没有考虑到的数字方法的缺点是:

  • 降低了解物体实际含义的能力is。 API 调用可能会失败,因为您传递的数字并不是真正的对象。或者更糟糕的是,如果将着色器对象传递给采用纹理的函数会发生什么?也许我们正在讨论一个需要着色器和纹理的函数,而您不小心忘记了参数的顺序?如果这些是对象指针,C++ 的规则甚至不允许该代码编译。但是对于整数呢?都很好;你只会得到运行时错误。

  • 表现。每个 API 调用都必须在哈希表或其他内容中查找该数字,以获得要使用的实际指针。如果它是一个哈希表(即:一个数组),那么它可能相当小。但这仍然是一个间接的。由于您的抽象看起来级别非常低,因此在性能关键的情况下,此级别的任何性能损失都会真正受到损害。

  • 缺乏 RAII 和其他范围机制。当然,你可以写一个shared_ptr-esque 对象将创建和删除它们。但如果您使用实际的指针,则不必这样做。

这似乎不值得。

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

我应该对不透明对象使用整数 ID 还是指针? 的相关文章

  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 重载<<的返回值

    include
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • 使用.NET技术录制屏幕视频[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一种方法可以使用 NET 技术来录制屏幕 无论是桌面还是窗口 我的目标是免费的 我喜欢小型 低
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • DCG和左递归

    我正在尝试实现一个 dcg 它采用一组 a b c d 形式的字符串 我遇到的问题是 如果我有一个 s a c b 它返回 true 这是正确的答案 但是当我有 s a c f 形式的查询时 它不会返回答案 并且会耗尽本地堆栈 s gt s
  • ftp_get 不适用于大文件

    这是我的代码 con ftp connect ftpserver com ftp login con username password ftp pasv con true ftp set option con FTP TIMEOUT SE
  • create-react-app 不会生成 public 和 src 文件夹,因此无法启动

    我已经安装 CRA 一个多月了 并且一直在使用它 没有任何问题 但是今天我创建了一个新的 React 应用程序 它构建了文件夹和目录 但它不生成 src 和公共文件夹 它只是生成节点 module 文件夹 因此当我运行 npm start
  • Cordova/phonegap 活动生命周期

    我正在cordova应用程序中为android开发一个地图插件 让我们暂时忘记已经有不止一个了 并认为这是一个学术问题 的文档MapView states http developer android com reference com g
  • PhoneGap/Cordova iOS:捕获有持续时间限制的视频(即 30 秒)

    我想将视频捕捉时间限制为 30 秒 截至目前 PhoneGap 文档说明了 iOS 实现的以下内容 不支持持续时间参数 无法以编程方式限制录制长度 我确实找到了这篇文章 它似乎给出了纯粹客观的 C 实现的解决方案 iPhone 5秒视频拍摄
  • os_signpost 在模拟器上有效,但在设备上运行时无效

    我想使用仪器跟踪时间的函数之一中有以下代码行 当我从仪器在模拟器上运行该应用程序时 使用 os signpost 测量的时间确实显示出来 我可以准确地测量我需要的东西 Then I switch to device same code Ho
  • R - 分割数据框并保存到不同的文件

    我有一个数据框 其中包含多个地点的每月温度数据 gt df4 1 36 location variable cut month year freq 1 Adamantina temperature 10 Jan 1981 21 0 646
  • 如何消除 SSIS 作业中的“未使用的输出列”警告?

    我正在尝试消除 SSIS 进度日志中的一些虚假警告 我收到一堆关于使用原始 SQL 完成工作的任务中未使用列的警告 我有一个数据流 负责在加载新数据之前将数据归档到临时表中 数据流如下所示 OLEDB Source task read st
  • Xcode 是否隐式将 plist 转换为二进制格式?

    Xcode 在构建过程中是否会隐式地将项目中的 plist 转换为二进制文件 我不认为它隐式地这样做 但很难确定 有一个名为 Property List Output Encoding 又名 PLIST FILE OUTPUT FORMAT
  • 如何修复SSL证书验证失败

    我在本地使用 PHPMailer Apache 和 PHP 当我测试我的 SSL 配置和我的 cacerts 时 我得到 default cert file C Program Files Common Files SSL cert pem
  • 在VB.NET中使用Moq的VerifySet

    我有一个功能可以更新 ASP NET 会员资格提供程序中的用户
  • Python Kivy:如何在单击按钮时调用函数?

    我对使用 kivy 库还很陌生 我有一个 app py 文件和一个 app kv 文件 我的问题是我无法在按下按钮时调用函数 app py import kivy from kivy app import App from kivy uix
  • 如何在 wpf 中使用 WindowChrome 而不使用 Windows Aero 玻璃效果,黑色边框

    我正在尝试使用 WindowChrome 类自定义窗口边框 没有 Windows Aero 玻璃效果 正如预期的那样 我最终得到了一个黑人寄宿生 但我最终也没有标题按钮 从微软我了解到我可以通过将窗口样式设置为 null 来使用标准窗口来克
  • DQL 查询返回:预期 StateFieldPathExpression 或 SingleValuedAssociationField

    我有以下 DQL 查询 public function findByIdJoinedToCodeExample pageId query this gt getEntityManager gt createQuery SELECT c FR
  • 将 super 与 class_eval 一起使用

    我有一个应用程序 其中包含用于添加客户端自定义的核心类模块 我发现 class eval 是重写核心类中方法的好方法 但有时我想避免重写整个方法 而只是遵循原始方法 例如 如果我有一个名为account balance 最好在我的模块 即包
  • 在 ASP.NET 中将 HTML 内容写入 Word 文档时出现问题

    我正在尝试将 HTML 页面内容导出到 Word 我的Html显示页面是 你最喜欢的颜色是什么 NA 列出前三名的学校 一名国家级 两个开发人员 三个PS 以及一个用于点击事件的按钮 按钮单击事件将打开 MS Word 并将页面内容粘贴到
  • 简单的 UIView drawRect 没有被调用

    我不明白这里出了什么问题 我有一个非常简单的 UIViewController 和一个非常简单的 viewDidLoad 方法 void viewDidLoad NSLog making game view GameView v GameV
  • Python-获取目录中所有文件和子文件夹的相对路径

    我正在寻找一种获取特定文件夹内文件和 子 文件夹的相对路径的好方法 对于我目前使用的方法os walk 它正在工作 但对我来说似乎并不 Pythonic myFolder myfolder fileSet set yes I need a
  • 手动设置Session过期时间-CodeIgniter

    如何在 codeigniter 中动态设置会话过期时间 例如 如果用户登录并具有以下角色 admin 过期时间应该比没有权限的用户登录时要长admin role Thanks 您可以通过在配置文件中增加此变量来更新会话过期时间 config
  • 我应该对不透明对象使用整数 ID 还是指针?

    我正在一些图形 API DirectX9 和 DirectX11 之上编写一个抽象层 我想听听您的意见 传统上 我会为每个我想要抽象的概念创建一个基类 因此 在典型的 OO 方式中 我将拥有一个 Shader 类和 2 个子类 DX9Sha