问题标签 [pimpl-idiom]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
11 回答
113337 浏览

c++ - 为什么要使用“PIMPL”成语?

背景资料:

PIMPL Idiom (指向 IPLementation的指针)是一种实现隐藏技术,其中公共类包装了在公共类所属的库之外无法看到的结构或类。

这对库的用户隐藏了内部实现细节和数据。

在实现这个习惯用法时,为什么要将公共方法放在 pimpl 类而不是公共类上,因为公共类的方法实现将被编译到库中并且用户只有头文件?

为了说明,此代码将Purr()实现放在 impl 类上并包装它。

为什么不在公共类上直接实现 Purr 呢?

0 投票
6 回答
2994 浏览

c++ - C++ 不能消除 pimpl 成语吗?

据我了解,pimpl 习惯用法的存在只是因为 C++ 强制您将所有私有类成员放在标题中。如果标头仅包含公共接口,理论上,类实现的任何更改都不需要重新编译程序的其余部分。

我想知道的是为什么 C++ 的设计不是为了提供这样的便利。为什么它要求一个类的私有部分在标题中公开显示(不是双关语)?

0 投票
2 回答
847 浏览

c++-cli - 在 C++/CLI 中使用 PIMPL 习惯用法时的 MSVC++ 链接器警告

我正在使用 C++/CLI(9.0 版)编写一个 .NET 程序集,并且我想使用 PIMPL 习惯用法来避免在我的公共标头中放置不必要的东西。不幸的是,当我尝试转发声明一个类,然后对其使用跟踪句柄时,我收到链接器警告 4248:

警告 LNK4248:“MyNamespace.PrivateClass”的未解析 typeref 令牌 (0100000E);图像可能无法运行

无论我对实现类使用 CLI 类还是本机类,这似乎都是这种情况。

示例代码如下所示:

不幸的是,微软对警告的解释并没有提供太多信息。

0 投票
5 回答
12091 浏览

c++ - 带有继承的 Pimpl 成语

我想将 pimpl 成语与继承一起使用。

这是基础公共类及其实现类:

我希望能够使用其实现类创建派生的公共类:

但是我不能在 B 中使用 pAimpl,因为它是 A 的私有的。

所以我看到了一些解决方法:

  1. 在 B 中创建 BImpl* pBImpl 成员,并使用附加的 A 构造函数 A(AImpl*) 将其传递给 A。
  2. 将 pAImpl 更改为受保护(或添加 Get 函数),并在 B 中使用它。
  3. B 不应该从 A 继承。在 B 中创建 BImpl* pBImpl 成员,并在 B 中创建 foo() 和 bar(),这将使用 pBImpl。
  4. 还有什么办法吗?

我应该选择什么?

0 投票
2 回答
708 浏览

c++ - 如何在 C++ 中获取抽象(?)pimpl 的调试信息?

我有一个包装类,它将其工作委托给一个 pimpl,而 pimpl 是一个指向基类/接口的指针,它没有以几种不同方式专门化的数据。

像这样:

现在这在大多数情况下都可以正常工作,但是当进入调试器时,我无法查看 Derived 类的 x,y (因为它可以是任何东西)。通常这是无关紧要的,但是当出现问题时,查看 Derived 的状态可能很重要,但是 pimpl 过于模糊了状态(但是这是 pimpl 的原始想法,所以我想我真的不能抱怨)。

现在我有一个 tostring() 函数,可以打印出状态以进行调试,但想知道是否有更好的解决方案,特别是在 VisualStudio 中调试这种结构,但一般的解决方案会更好。

谢谢

0 投票
10 回答
25600 浏览

c++ - Pimpl 成语 vs 纯虚拟类接口

我想知道是什么让程序员选择 Pimpl 习惯用法或纯虚拟类和继承。

我知道 pimpl idiom 为每个公共方法和对象创建开销都提供了一个明确的额外间接。

另一方面,纯虚拟类带有用于继承实现的隐式间接(vtable),我知道没有对象创建开销。
编辑:但是如果你从外部创建对象,你需要一个工厂

是什么让纯虚拟类比 pimpl 成语更不受欢迎?

0 投票
8 回答
21449 浏览

c++ - 实践中的 Pimpl 成语

关于pimpl idiom有一些关于 SO 的问题,但我更好奇它在实践中的使用频率。

我知道在性能和封装之间存在一些权衡,以及由于额外的重定向而导致的一些调试烦恼。

有了这个,这是应该在每个班级还是全有或全无的基础上采用的东西?这是最佳实践还是个人偏好?

我意识到这有点主观,所以让我列出我的首要任务:

  • 代码清晰
  • 代码可维护性
  • 表现

我总是假设我需要在某个时候将我的代码公开为一个库,所以这也是一个考虑因素。

编辑:完成同样事情的任何其他选项都是受欢迎的建议。

0 投票
6 回答
2147 浏览

c++ - 您使用什么模式来解耦 C++ 中的接口和实现?

大型 C++ 项目中的一个问题可能是构建时间。在你的依赖树中有一些你需要处理的类,但通常你会避免这样做,因为每次构建都需要很长时间。您不一定要更改其公共接口,但也许您想更改其私有成员(添加缓存变量,提取私有方法,...)。您面临的问题是,在 C++ 中,甚至私有成员都在公共头文件中声明,因此您的构建系统需要重新编译所有内容。

在这种情况下你会怎么做?

我已经勾勒出两种我知道的解决方案,但它们都有自己的缺点,也许还有一个更好的我还没有想到的解决方案。

0 投票
5 回答
1498 浏览

c++ - pimpl 成语和模板类朋友

我正在尝试使用 pimpl 习惯用法来隐藏一些蹩脚的模板代码,但我不能让 body 类的派生类访问句柄类。我从 MSVC 9 sp1 收到错误 C2248。这是一些复制错误的代码:

任何帮助将不胜感激,我试图向用户隐藏interface::bodyspecific_body实施,interface如果这在我的问题中并不明显。

0 投票
3 回答
1489 浏览

c++ - 自动化 C++ 类的 pimpl'ing - 有没有简单的方法?

Pimpl's 是许多 C++ 代码中样板文件的来源。它们似乎是宏、模板和一些外部工具的组合可以解决的问题,但我不确定最简单的方法是什么。我已经看到模板可以帮助完成一些提升,但并不多——您最终仍然需要为您尝试包装的类的每个方法编写转发函数。有没有更简单的方法?

我在想象一个工具用作制作过程的一部分。您希望您的公共标头是 pimpl'd 类,因此您提供一些输入文件,例如 pimpl.in,其中列出了您想要包装的类(实现 un-pimpl'd),然后检查该文件,生成 pimpl 类,并且在“make install”期间仅安装它们的头文件(不是原始类的头文件)。问题是如果没有完整的 C++ 解析器,我看不到任何方法可以做到这一点,即使是编译器供应商也无法做到这一点。也许这些类可以以某种方式编写,使外部工具的工作更容易,但我确信我最终会错过各种极端情况(例如模板化类和/或模板化成员函数)。

有任何想法吗?有没有其他人已经为这个问题提供了解决方案?