问题标签 [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.
c++ - 使用私有继承隐藏实现是个好主意吗?
例如
这似乎类似于Pimpl 成语。这有两个我非常喜欢的优点:
- SomePrivateMethod 是可测试的。如果 SomePrivateMethod 在 Point 中被声明为私有,您将无法从测试中调用它。如果您在 Point 中将其声明为 public 或 protected,测试将能够调用它,但 Point 的普通用户也可以调用它。
- 与您在 Pimpl 惯用语中的操作相比,访问私有数据更容易读写,因为您不必通过指针,例如
.
对比
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不能解决我的问题,因为它们绑定到单个实现。
c++ - 对库用户隐藏库依赖项
考虑我正在编写一个静态库。让它有一个类Foo
如您所见,这个库(让我们称之为mylib
)依赖于另一个库。它编译得很好。但是当用户编译它的代码(使用Foo
和包含mylib.h
)并与我的库链接时,编译失败,因为用户还需要有dependency_header_from_other_static_library.h
头文件来编译代码。
我想对用户隐藏这种依赖关系。如何做到这一点?想到的一件事是PIMPL
成语。喜欢:
但这需要我Foo
在FooImpl
. 而且,PIMPL
在我的情况下使用它是否有点矫枉过正?
谢谢。
c++ - 使用指针隐藏实现(Pimpl idiom)
是否有可能完成以下任务:
x.hpp - 此文件包含在许多其他类中
x.cpp - 实现
所以基本上,我希望用户包含文件x.hpp,但不知道conrete_x.hpp标头。
由于我concrete_x
只能通过指针使用并且它仅作为私有数据成员出现,因此前向声明应该足以让编译器知道为它准备多少空间。它看起来很像著名的“pimpl idiom”。
你能帮我解决这个问题吗?
PS。我不想使用 avoid*
并对其进行投射..
c++ - 将 Objective-C 实例转换为 C++ 类
如何将 Objective-c 类实例化为 CPP 类?
例如我的 CPP 课程:
我怎么能这样做?
请注意,我将 .m 用于 Objective-C,将 .cpp 用于 C++。
非常感谢!
c++ - 从私有嵌套类型继承在 C++11 中是否合法?
我想要做的是在我的库类中将可变大小的 POD 作为 Pimpl:
然后像这样定义几个固定大小的实现:
GCC 版本 4.6 和 4.7 用 编译这个没有问题-std=c++0x -Wall -pedantic
,但我仍然对使用这样的私有嵌套类型名称的合法性感到模糊。翻阅我的 C++11 标准的 [可能是过时的草案] 副本并没有给我任何更好的线索。
如果有人能指出我的任何东西(最好是标准中的一个部分)可以证明这种方式或另一种方式(合法与否),我将永远感激不尽。
c++ - 类 C 实现的 C++ 等效性能版本
当我遇到这种情况时,我正在学习 C++,我想在 C++ 中实现以下 C 符号代码的等效有效版本。
要求是:
- 该实现在库(静态/动态)中提供,并且标头不公开除接口以外的任何细节
- 它应该同样有效
使用虚函数公开接口(类 COM)是不合格的;这是一种启用多态性(通过同一接口公开多个实现)的解决方案,但事实并非如此,而且由于我不需要它带来的价值,我不明白为什么我应该支付调用函数的成本通过2个间接指针。所以我的下一个想法是 pimpl 成语:
shared_ptr<> 似乎不符合条件,我会为原始实现中不存在的不必要的互锁递增/递减付费。另一方面, unique_ptr<> 使 Obj 不可复制。这意味着客户端不能调用他自己的函数来获取 Obj 的值,而 Obj 只是一个指针的包装器,所以本质上他不能通过值传递指针!他可以在原始版本中做到这一点。(通过引用传递仍然不合格:他仍在传递指向指针的指针)
那么在 C++ 中实现这一点的同样有效的方法应该是什么?
编辑:我给了它更多的想法,我来到了这个解决方案:
现在我回到客户端Obj,如果客户端需要通过调用他的一些其他函数来分配Obj的使用,他可以将它们声明为
c++ - Pimpl + QSharedPointer - 析构函数 = 灾难
昨天我遇到了痛苦,这让我沮丧了 24 小时。问题归结为随机发生的意外崩溃。更复杂的是,调试报告也有绝对随机的模式。更复杂的是,所有调试跟踪都导致随机Qt 源或本地 DLL,即每次都证明问题不在我这边。
这里有一些这样可爱的报告的例子:
正如您所看到的,这些东西非常讨厌,它没有提供任何有用的信息。但是,有一件事我没有注意。这是编译期间的一个奇怪的警告,也很难用眼睛捕捉到:
实际上,我只是将这个警告作为最后的手段,因为在如此绝望地寻找错误的过程中,代码已经感染了字面上的日志死亡。
仔细阅读后,我想起了,例如,如果使用std::unique_ptr
或std::scoped_ptr
用于Pimpl - 肯定应该提供析构函数,否则代码甚至无法编译。但是,我还记得它std::shared_ptr
不关心析构函数并且没有它也可以正常工作。这也是我没有注意这个奇怪警告的另一个原因。长话短说,当我添加析构函数时,这种随机崩溃停止了。看起来 QtQSharedPointer
与std::shared_ptr
. 我想如果 Qt 开发人员将此警告转化为错误会更好,因为这样的调试马拉松根本不值得花时间、精力和精力。
我的问题是:
- 有什么问题
QSharedPointer
?为什么析构函数如此重要? - 为什么在没有析构函数的情况下会发生崩溃?这些对象(使用Pimpl +
QSharedPointer
)是在堆栈上创建的,并且在它们死后没有其他对象可以访问它们。然而,坠机发生在他们死后的某个随机时间段内。 - 有没有人遇到过这样的问题?请分享你的经验。
- Qt 中是否还有其他类似的陷阱——我必须知道这些陷阱以确保将来保持安全?
希望这些问题和我的一般帖子能帮助其他人避免我过去 24 小时去过的地狱。
c++ - 为什么是二进制兼容性?
我正在学习 PIMPL 成语。它的优点之一是二进制兼容性。我想知道二进制兼容性的优点是什么。谢谢!
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
基于一个旧版本的复制和粘贴失败的调用。