问题标签 [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 投票
3 回答
288 浏览

c++ - 使用私有继承隐藏实现是个好主意吗?

例如

这似乎类似于Pimpl 成语。这有两个我非常喜欢的优点:

  1. SomePrivateMethod 是可测试的。如果 SomePrivateMethod 在 Point 中被声明为私有,您将无法从测试中调用它。如果您在 Point 中将其声明为 public 或 protected,测试将能够调用它,但 Point 的普通用户也可以调用它。
  2. 与您在 Pimpl 惯用语中的操作相比,访问私有数据更容易读写,因为您不必通过指针,例如

.

对比

0 投票
4 回答
2107 浏览

c++ - 指向可配置实现的 Pimpl 成语

我读过 Pimpl 有利于二进制兼容性,接口有利于能够轻松切换实现。我需要结合这两种技术,以使我的应用程序能够通过配置文件切换底层实现。

这是我目前的设计的布局方式:

class Foo:提供面向客户端的 API,我关心的是 ABI 兼容性
class IFoo:接口类(所有纯虚拟方法,virtual dtor)
class Vendor1Foo:实现 IFoo,使用 Vendor1 的库
class Vendor2Foo:实现 IFoo,使用 Vendor2 的库

通过不使用 pimpl 并严格使用接口,客户端代码可能如下所示:

问题是我的客户端代码根本不知道 Vendor1 或 Vendor2,而 Foo 只是我必须为此做的众多类之一。

我正在尝试做的总体概念如下:

有什么想法可以优雅地解决这个问题吗?

我希望提出一些宏或模板类/方法来帮助标准化我如何处理这个问题并尽量减少违反 DRY。

模板类可以作为一个 pimpl 助手,就像 Herb Sutter 对 C++11 的通用 pimpl idiom 所做的那样:herbsutter.com/gotw/_101,它还必须包含根据配置实例化正确实现的逻辑

这里有 pimpl 成语、桥接模式和工厂模式的元素。在我上面的例子中,initImpl() 可以被认为是一个工厂方法。我正在寻找一种可能会或可能不会使用所有这些模式的解决方案。

我已经查看了c++ pimpl idiom : Implementation based on a template parameter以及关于 SO 的大多数 pimpl idiom questions。标题看起来很有希望,但它对我的特定用例没有帮助。

我不能使用 C++11 并且正在使用 Qt。 D-Pointers不能解决我的问题,因为它们绑定到单个实现。

0 投票
1 回答
1101 浏览

c++ - 对库用户隐藏库依赖项

考虑我正在编写一个静态库。让它有一个类Foo

如您所见,这个库(让我们称之为mylib)依赖于另一个库。它编译得很好。但是当用户编译它的代码(使用Foo和包含mylib.h)并与我的库链接时,编译失败,因为用户还需要有dependency_header_from_other_static_library.h头文件来编译代码。

我想对用户隐藏这种依赖关系。如何做到这一点?想到的一件事是PIMPL成语。喜欢:

但这需要我FooFooImpl. 而且,PIMPL在我的情况下使用它是否有点矫枉过正?

谢谢。

0 投票
4 回答
4908 浏览

c++ - 使用指针隐藏实现(Pimpl idiom)

是否有可能完成以下任务:

x.hpp - 此文件包含在许多其他类中

x.cpp - 实现

所以基本上,我希望用户包含文件x.hpp,但不知道conrete_x.hpp标头。

由于我concrete_x只能通过指针使用并且它仅作为私有数据成员出现,因此前向声明应该足以让编译器知道为它准备多少空间。它看起来很像著名的“pimpl idiom”。

你能帮我解决这个问题吗?

PS。我不想使用 avoid*并对其进行投射..

0 投票
2 回答
156 浏览

c++ - 将 Objective-C 实例转换为 C++ 类

如何将 Objective-c 类实例化为 CPP 类?

例如我的 CPP 课程:

我怎么能这样做?

请注意,我将 .m 用于 Objective-C,将 .cpp 用于 C++。

非常感谢!

0 投票
2 回答
566 浏览

c++ - 从私有嵌套类型继承在 C++11 中是否合法?

我想要做的是在我的库类中将可变大小的 POD 作为 Pimpl:

然后像这样定义几个固定大小的实现:

GCC 版本 4.6 和 4.7 用 编译这个没有问题-std=c++0x -Wall -pedantic,但我仍然对使用这样的私有嵌套类型名称的合法性感到模糊。翻阅我的 C++11 标准的 [可能是过时的草案] 副本并没有给我任何更好的线索。

如果有人能指出我的任何东西(最好是标准中的一个部分)可以证明这种方式或另一种方式(合法与否),我将永远感激不尽。

0 投票
2 回答
175 浏览

c++ - 类 C 实现的 C++ 等效性能版本

当我遇到这种情况时,我正在学习 C++,我想在 C++ 中实现以下 C 符号代码的等效有效版本。

要求是:

  • 该实现在库(静态/动态)中提供,并且标头不公开除接口以外的任何细节
  • 它应该同样有效

使用虚函数公开接口(类 COM)是不合格的;这是一种启用多态性(通过同一接口公开多个实现)的解决方案,但事实并非如此,而且由于我不需要它带来的价值,我不明白为什么我应该支付调用函数的成本通过2个间接指针。所以我的下一个想法是 pimpl 成语:

shared_ptr<> 似乎不符合条件,我会为原始实现中不存在的不必要的互锁递增/递减付费。另一方面, unique_ptr<> 使 Obj 不可复制。这意味着客户端不能调用他自己的函数来获取 Obj 的值,而 Obj 只是一个指针的包装器,所以本质上他不能通过值传递指针!他可以在原始版本中做到这一点。(通过引用传递仍然不合格:他仍在传递指向指针的指针)

那么在 C++ 中实现这一点的同样有效的方法应该是什么?

编辑:我给了它更多的想法,我来到了这个解决方案:

现在我回到客户端Obj,如果客户端需要通过调用他的一些其他函数来分配Obj的使用,他可以将它们声明为

0 投票
2 回答
1894 浏览

c++ - Pimpl + QSharedPointer - 析构函数 = 灾难

昨天我遇到了痛苦,这让我沮丧了 24 小时。问题归结为随机发生的意外崩溃。更复杂的是,调试报告也有绝对随机的模式。更复杂的是,所有调试跟踪都导致随机Qt 源或本地 DLL,即每次都证明问题不在我这边。

这里有一些这样可爱的报告的例子:



正如您所看到的,这些东西非常讨厌,它没有提供任何有用的信息。但是,有一件事我没有注意。这是编译期间的一个奇怪的警告,也很难用眼睛捕捉到:

实际上,我只是将这个警告作为最后的手段,因为在如此绝望地寻找错误的过程中,代码已经感染了字面上的日志死亡。

仔细阅读后,我想起了,例如,如果使用std::unique_ptrstd::scoped_ptr用于Pimpl - 肯定应该提供析构函数,否则代码甚至无法编译。但是,我还记得它std::shared_ptr不关心析构函数并且没有它也可以正常工作。这也是我没有注意这个奇怪警告的另一个原因。长话短说,当我添加析构函数时,这种随机崩溃停止了。看起来 QtQSharedPointerstd::shared_ptr. 我想如果 Qt 开发人员将此警告转化为错误会更好,因为这样的调试马拉松根本不值得花时间、精力和精力

我的问题是:

  1. 有什么问题QSharedPointer?为什么析构函数如此重要?
  2. 为什么在没有析构函数的情况下会发生崩溃?这些对象(使用Pimpl + QSharedPointer)是在堆栈上创建的,并且在它们死后没有其他对象可以访问它们。然而,坠机发生在他们死​​后的某个随机时间段内。
  3. 有没有人遇到过这样的问题?请分享你的经验。
  4. Qt 中是否还有其他类似的陷阱——我必须知道这些陷阱以确保将来保持安全?

希望这些问题和我的一般帖子能帮助其他人避免我过去 24 小时去过的地狱。

0 投票
3 回答
755 浏览

c++ - 为什么是二进制兼容性?

我正在学习 PIMPL 成语。它的优点之一是二进制兼容性。我想知道二进制兼容性的优点是什么。谢谢!

0 投票
2 回答
1982 浏览

c++ - 带有 pimpl 习惯用法的模板类不正确

正如 MSDN library here中所述,我想尝试一下 pimpl idiom。现在我有Foo.hpp一个

尚未T使用参数的地方。实现存储在Foo.cpp

目前编译器有两个错误和一个警告:

  • use of undefined type 'Foo<T>::Impl'; ... vc\include\memory in line 1150
  • can't delete an incomplete type; ... vc\include\memory in line 1151
  • deletion of pointer to incomplete type 'Foo<T>::Impl'; no destructor called; ... vc\include\memory in line 1152

这里有什么冲突,我该如何解决?

编辑。删除了对std::make_shared基于一个旧版本的复制和粘贴失败的调用。