C++ 令人头疼的命名空间

2024-05-03

好吧,这个问题已经发生了一些变化,我想尝试从我正在追求的基本目标开始(重新):

  • 创建在 C++ 资源获取和初始化中包装遗留 C 语言实体的库代码,并提供基本或更好的异常保证。
  • 使此代码的客户端能够以非常自然的 C++ 方式使用它,而不会为现有代码创建大量开销以将其转换为使用 C++ 包装对象(即自动转换为适当的遗留类型、采用遗留类型的构造函数等) .)
  • 限制库代码的命名空间影响。理想情况下,该库将具有多个子命名空间,这些子命名空间提供相关功能,限制使用命名空间 X 类型声明的数量和影响 - 就像 boost 库所做的那样(即使用详细命名空间仅注入用户合理想要的那些符号使用并隐藏那些实现细节;还限制现有符号可能的新含义的范围,以避免用户代码中令人惊讶的隐式转换)
  • 要求客户明确请求他们实际想要注入到代码库中的库的那些部分。这与限制包含库标头的影响密切相关。客户端代码应该对编译代码时自动使用库的哪些部分进行名称解析有合理的控制级别。
  • 我自己的库代码不应该充满重构脆弱的代码结构。如果库的标头不必不断声明私有 typedef 来访问库的该部分的其余部分,那就太理想了。或者换句话说:我希望我的库能够像我的客户在使用该库时一样直观地编写。除了已明确“使用”的任何其他命名空间之外,名称解析还应包括定义库的命名空间。

我经常遇到这种情况,正在寻找更好的方法......

我有一个类 C,位于命名空间 N 中。C 有一个成员 Free。 C 管理的东西是免费的,并且允许 C 管理新的东西。

有几个全局免费函数。在与 C 相同的命名空间 N 中还有一些辅助函数,其中之一是 free 是 C 管理的东西的辅助函数,名为 free。

所以我们有这样的东西:

namespace N {

void free(THING * thing);

class C
{
public:
  ... details omitted...
  free()
  { 
    free(m_thing); // <- how best to refer to N::free(THING&)
  }
}

} // namespace N

我可以使用 N::free(m_thing)。但这对我来说似乎很不幸。是否没有办法引用类范围之外的内容,但又不解析绝对名称空间(相对范围内的一步)?

在我看来,必须命名 N::free 是令人讨厌的,因为如果这是一个独立的函数,则不必这样做。如果类的方法名称碰巧不同(例如 dispose),您也不需要这样做。但因为我使用了相同的名称,所以如果您愿意接受我的类比,我就无法在不指定绝对路径(而不是相对路径)的情况下访问它。

我讨厌绝对路径。它们使得在命名空间中移动东西变得非常脆弱,因此代码重构变得更加难看。另外,如何在函数体中命名事物的规则随着当前的一组规则(据我所知)而变得更加复杂 - 不太规则 - 导致人们期望的东西和作为程序员得到的东西之间的分裂。

有没有更好的方法来访问与类相同的命名空间中的独立函数,而不必绝对命名自由函数?

编辑: 也许我应该举一个不太抽象的例子:

namespace Toolbox {
  namespace Windows {

// deallocates the given PIDL
void Free(ITEMIDLIST ** ppidl);

class Pidl
{
public:
    // create empty
    Pidl() : m_pidl(NULL) { }

    // create a copy of a given PIDL
    explicit Pidl(const ITEMIDLIST * pidl);

    // create a PIDL from an IShellFolder
    explicit Pidl(IShellFolder * folder);

    ...

    // dispose of the underlying ITEMIDLIST* so we can be free to manage another...
    void Free();
};

因此 ITEMIDLIST* 来自各个地方,并被 CoTaskMemFree() 销毁。我可以引入 Pidl 作为全局名称 - 以及“Windows Shell.h”标头中的所有辅助函数,该标头是我的工具箱库的一部分。

理想情况下,我会根据库中的一些工具的相关内容对它们进行细分 - 在本例中,上述所有工具都与 Windows 中的 COM 编程相关。我选择 Toolbox 作为我的库内容的基本命名空间,并且目前正在考虑将 Toolbox::Windows 用于非常 Windows 的函数、类等。

但 C++ 命名空间和名称解析规则似乎使这变得非常困难(因此出现了这个问题)。创建这样的代码分段非常不自然 - 因为 koenig 查找失败(因为 ITEMIDLIST 不在我的 Toolbox::Windows 命名空间中),而且我无法将其移动到那里!我也不应该。在我看来,该语言应该足够灵活,以允许扩展库(例如我的 Toolbox 库)扩展其他人的代码,而不必将我的扩展注入到他们的命名空间中(在 Win32 和一般广泛的情况下)今天存在的大多数代码都是 GLOBAL NS - 这就是首先创建名称空间的全部目的:避免全局 NS 拥挤/污染/歧义/编程意外)。

所以,我回过头来,有没有更好的方法来做到这一点:扩展现有的代码库,同时不会用我的扩展污染他们的 NS,但仍然允许直观和有用的名称解析,正如人们所期望的那样,如果我的代码在他们的 NS 中,但由我的客户明确引入代码(即我不想随意注入我的代码,但只有在明确请求时才注入)?

另一个想法:如果我具有以下条件,也许可以满足我的上述标准:

using namespace X {
  code here...
}

我可以将这样的构造放在任何地方,包括在标头中,并且我不必担心将 X 拖到我的客户代码中,但我将拥有与在根命名空间。


我认为无法避免必须限定命名空间范围free()这里,但需要注意的是,这与“绝对路径”不同。一方面,如果您有嵌套命名空间,则只需引用最里面的命名空间:

namespace N1 {
  namespace N2 {
    namespace N3 {
      void free(THING * thing);

      class C {
      public:
        free() {
          N3::free(m_Thing); // no need to do N1::N2::
        }
      };
    }
  }
}

[EDIT]回答已编辑的问题。同样,在您描述的具体场景中,我看不到任何方法可以做到这一点。然而,这似乎不是惯用的 C++ 方法 - 更常见的方法是提供您自己的包装类ITEMIDLIST管理所有分配,RAII 风格,并公开原始句柄(例如,通过 ATL 中的转换运算符,或显式成员函数,如c_str()如果您想要额外的安全)。这将消除您的需要free总的来说,对于您可能需要的任何其他自由函数,由于您控制包装器类型及其所在的命名空间,因此您可以像往常一样使用 ADL。

[编辑#2]。这部分问题:

允许直观且有用的名称解析,正如人们所期望的那样,如果我的代码位于他们的 NS 中,但由我的代码的客户端明确引入(即我不想随意注入我的代码,但是仅在明确要求时)?

这不就是你把它放在命名空间中,而你的客户写的吗?using namespace ...,会实现吗?

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

C++ 令人头疼的命名空间 的相关文章

  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

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

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • 提升灵气自定义综合属性(通过语义动作设置结构体属性的特定成员)

    假设我有一个结构体 我想用灵气解析成 它的定义如下 struct data bool export std wstring name data export false 另外 假设该结构已适应融合 如下所示 BOOST FUSION ADA
  • 如何读取从 Access 导入的 SAS 数据集(不符合 SAS 命名约定)

    我已使用 Libname 将 Access DB 导入 SAS 库名称 accdb c mydata base accdb DB 中的所有表现在都在 accdb 库中 但 Access DB 中的表名称与 SAS 数据集命名约定不匹配 我的
  • 将泛型与 Firebase snapshot.getValue() 结合使用的最佳实践

    TL DR 如何正确使用 Firebase DataSnapshot getValue 的泛型类 用例 我想使用 Firebase 为我的所有实体 其中一堆 实现一个通用远程数据源类 当监听数据更改时 我想从 datasnapshot 获取
  • Android Studio 中过时的 Kotlin 运行时警告

    下载并安装最新的 Kotlin 插件后 我有过时的 Kotlin 运行时来自 Android Studio 的警告告诉我 您在 kotlin stdlib 1 1 2 库中的 Kotlin 运行时版本是 1 1 2 而插件版本是1 1 2
  • 从 PHP/Web 应用程序打印多个标签到 Dymo LabelWriter 450 Turbo

    我希望添加使用 Dymo LabelWriter 450 Turbo 打印多个标签的功能 我已经从 Dymo 网站下载了 DYMO Label v 8 SDK dmg 但看不到任何 Javascript Web 相关的 SDK 文件或文档
  • 如何在D3中导入json数据?

    如何在D3中导入json文件 I did d3 json temp json 但是我如何在进一步的代码中访问这个数据集呢 到目前为止我已经尝试过 var data d3 json temp json 但使用 data data 在其余代码中
  • 使用 ffmpeg 从 unix 命令批量将 wav 文件转换为 16 位

    我有一个由许多子文件夹组成的文件夹 每个子文件夹都有其他子文件夹 其中包含 wav 文件 我想像这样转换所有文件 ffmpeg i BmBmGG BmBmBmBm wav acodec pcm s16le ar 44100 BmBmGG B
  • 使用 RSQLite 库时加载 MacPorts SQLite3

    我在 SQLite 一个计算乘积的聚合器 中有一个用户定义的函数 它在 R 之外工作得很好 但是我有时在 Mac 上 如果您想添加您的 SQLite3 则需要 MacPorts 版本的 SQLite3自己的功能 扩展 我可以选择 RSQLi
  • 在 Angular 中将图像 url 转换为 base64

    我正在努力尝试将给定的图像 url 转换为 base64 在我的例子中 我有一个带有图像路径的字符串 var imgUrl assets logoEmpresas empresa logoUrl 我如何直接将给定的图像网址转换为base64
  • 具有自定义计数标准的 RxJava 缓冲区/窗口

    我有一个 Observable 它发出许多对象 我想使用以下方法对这些对象进行分组 window or buffer运营 但是 不是指定count用于确定窗口中应有多少对象的参数我希望能够使用自定义标准 例如 假设可观察对象正在发出 a 的
  • 这是我尝试安装 pip3 时得到的结果

    这是我尝试安装 pip3 时得到的结果 sudo apt get install python3 pip Reading package lists Done Building dependency tree Reading state i
  • 将 cmake 与自定义文件生成器结合使用

    我想使用 CMake 生成混淆的 lua 文件以供交付 在我的一生中 我无法让 add custom command add custom target 为我构建这些文件 我缺少一些东西 ADD CUSTOM TARGET LUABIND
  • 使用 DropWizard Hibernate 进行单元测试时显示“当前没有会话绑定到执行上下文”

    我将 DW 与 Hibernate 结合使用 并尝试为我的 DAO 编写单元测试 我的代码基于这个例子 https github com dropwizard dropwizard blob 1310d7c981581b4e1be97104
  • 是否可以更改 WPF 控件的父级

    是否可以更改 WPF 控件的父控件 这是一个例子 StackPanel堆栈1有Buttonbtn1 在里面 还有一个空的StackPanel堆栈2 我想以编程方式将 btn1 移动到 stack2 谢谢您的帮助 您可以通过以下方式执行此操作
  • 将尾部输出重定向到程序中

    我想使用 tail 作为标准输入向程序发送文本文件中的最新行 首先 我向程序回显一些每次都相同的输入 然后从输入文件发送尾部输入 该输入文件应首先通过 sed 处理 以下是我期望工作的命令行 但是当程序运行时 它只接收回显输入 而不接收尾部
  • 混淆 bash 中存储的密码

    我有一个 bash 脚本 我需要编写密码才能运行程序 其他人可以看到它 有没有办法把密码写得不太明显 即使他可以在 bash 中执行相同的命令并获取密码 他也无法读取文本形式的密码 今天我这样做 PASSWORD 1234567 progr
  • TypeScript 中类似字典的对象应使用什么类型?

    在 TypeScript 中 我有时会使用期望 或返回 对象的函数 其中这些对象被视为字典 基本上我的问题是 这里使用的正确类型是什么 我可以用 Record
  • 使用 asyncore 读取网站

    我想异步阅读一个网站 据我所知 这是不可能的 urllib 现在我尝试使用普通套接字进行阅读 但是 HTTP 给我带来了麻烦 我遇到了各种时髦的编码 例如传输编码 分块 必须手动解析所有这些东西 我现在想编码 C 而不是 python 难道
  • C++ 析构函数和函数调用顺序

    假设我有以下代码片段 Foo foo return bar 现在 C 标准是否保证 bar 将在 foo Foo 之前调用 或者这是编译器 实现的选择 Thanks 这是有保证的行为 实际执行过程如下 0 enter block scope
  • C++ 令人头疼的命名空间

    好吧 这个问题已经发生了一些变化 我想尝试从我正在追求的基本目标开始 重新 创建在 C 资源获取和初始化中包装遗留 C 语言实体的库代码 并提供基本或更好的异常保证 使此代码的客户端能够以非常自然的 C 方式使用它 而不会为现有代码创建大量