问题标签 [pimpl]

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 投票
1 回答
217 浏览

c++ - 在类内将不完整类型的 unique_ptr 初始化为 nullptr 时使用 gcc 编译错误

我正在使用带有 unique_ptr 的 pimpl idiom 编写一些代码。当我尝试使用类内初始化将unique_ptr默认设置为nullptr时,gcc给出了编译错误,而clang和msvc都成功编译了代码。如果我不使用类内初始化,错误就会消失。

当我编译上述代码时,gcc 抱怨“错误:'sizeof' 对不完整类型'B' 的无效应用”。我已经尝试过 gcc 8.3 和 gcc 9.1 都没有成功。这是编译器错误吗?谢谢!

编辑: 我按照@eerorika 的建议进行了尝试。如果头文件和源文件合并为一个文件,可以正常编译,但不能分开。

编辑 确认是编译器错误并已在 gcc9.2 中修复。

0 投票
3 回答
85 浏览

c++ - 为什么在 PIMPL 中不能访问实现类的常量函数?

我想在 C++ 中尝试 PIMPL。

就我而言,我正在使用operator()访问私人成员。

接口类A和实现类AImpl都有operator() constoperator()

代码如下所示:

我使用以下命令编译程序

结果表明:

从结果可以看出:

A的 const 成员函数const int &A::operator()() const调用int &AImpl::operator()(),但不调用const int &AImpl::operator()() const.

为什么会这样?

在 PIMPL 的情况下,我希望 A 中的成员函数和 AImpl 是一一对应的。

我想const int &A::operator()() const打电话const int &AImpl::operator()() const

我怎样才能修改我的代码来实现这一点?修改会降低任何性能吗?

上面提到的是一个简单的案例。在实际情况下,A 是一个容器,将在我的代码中广泛使用,因此我不希望修改降低性能。

如果这是一个愚蠢的问题,我深表歉意。谢谢你的时间。

0 投票
2 回答
290 浏览

c++ - C++ pimpl 成语和导出数据结构

我有一个关于 pimpl 模式的问题,也许你们中的一个人可以想出一个我可能错过的解决方案。我已经实现了 pimpl 模式以将我的 dll 中的实现从世界其他地方隐藏起来,但我一直坚持如何隐藏需要从 dll 中导出的结构。下面是我的问题的简单表示(省略了一些部分)

idcom.h

idcom.cpp

idcom_impl.h

如果我想用另一个变量扩展 ListItemstd::string var3并且不破坏 ABI 并从 dll 中获取“listitem”列表,我有什么选择?我知道,为了让应用程序了解有关“ListItem”的一些信息,必须导出这个结构,但这是否足够,这是一个好的设计

0 投票
1 回答
159 浏览

c++ - 硬件抽象层(HAL)中实现的动态切换

我正在尝试实现一个硬件抽象层(HAL)来使用所有相同的接口访问几个类似的设备。问题是,我应该如何实现一个设备类与另一个设备类的实现的动态切换。
以下代码显示了我实际上是如何做到的。但是,我不确定这个实现是否足够安全。特别是我不确定使用“shared_ptr”来切换实现是否是正确的方法,或者使用工厂模式甚至更多抽象是否会更好。你会推荐什么来实现这样一个动态的 HAL?

我为所有设备定义了一个具有通用功能的基类(在此示例中,这只是Identify()方法)。然后我派生设备实现的类Derived1Derived2. 我想在主代码中的这些实现之间切换(例如设备选择器或类似的东西。在示例中,这只是通过从主代码调用设置器来完成)。
为了实现切换,我在当前实现中添加了一个类ImplementationDispatchershared_ptr用于隔离目的,类似于 pimpl-idiom。切换是通过向切换器类提供来自基的子类的新实例来完成的。

0 投票
2 回答
273 浏览

c++ - 如何使用 PIMPL 方法从原始类访问 impl 类的私有成员

我正在使用 PIMPL 方法,并希望从常规类访问实现类的私有成员。有什么合法的方法可以做到这一点吗?在下面的代码中,我想访问两个私有成员。其中一个是属性,另一个是方法。

这是我的代码:

戴夫.h

戴夫.cc

DaveImpl.h

DaveImpl.cc

当我编译上述代码时,我收到以下消息:

在上述场景中,我有什么方法可以访问“age”属性或“getIq”方法吗?

请注意,我坚持认为实现类中的成员和方法是私有的。不幸的是,我无法改变这一点。

0 投票
1 回答
31 浏览

c++ - 寻找一种方法来使用 PIMPL 与实现内部数组大小的外部常量定义

我们有以下情况:我们正在使用在其 RAM 中定义了部分的处理器,这些部分必须由使用 PIMPL 原则的特殊实现使用。例如,私有实现看起来像这样:

如您所见,此处未定义 DATA_SIZE。这里的重点是,我们可以在同一供应商的不同处理器上使用 Impl 中的处理器供应商提供的函数,并使用不同的链接脚本定义“data_buffer”部分。这是可能的,因为使用的底层系统为同一家族的不同处理器提供了相同的功能。但它必须是一个 PIMPL 来保证如果我更换到另一个供应商的不同处理器,我们可以为另一个供应商使用另一个 Impl。因此,可能有人正在使用具有不同 DATA_SIZE 的部分,因为他在他的项目中以不同的方式定义了他的部分(即使在同一个处理器上)。初始化和一切当然将通过构造函数等完成。

但是是否可以使 DATA_SIZE 可设置而不是直接在 Impl-File 中定义它?

据我所知,PIMPL 的目标是编译它并定义一个 ABI,这对我来说意味着编译后的文件在链接后不能改变大小。我的想法对吗?(对我来说,现在只是快速更改实现,永远不要接触上层使用 PIMPL 的软件部分,但我们将来会使用“pimpl-library”,我们只想更改编译后的 Impl-文件。)

我想防止使用派生的基类/接口类来完全隐藏对开发人员的实现,并且不传递派生类的任何引用或指针,因为这需要在上层进行软件更改。

谢谢你的想法。

0 投票
1 回答
234 浏览

c++ - Is pimpl idiom better than using always unique_ptr as member variables?

In my workplace we have this convention: almost every class (with very few exceptions) is implemented with unique_ptrs, raw pointers or references as member variables.

This is because of compilation times: in this way you just need a forward declaration for the class in your header file and you only need to include the file in your cpp. In addition if you change the .h or the .cpp of a class that you are including with unique_ptr you will not need to recompile.

I think that this pattern has at least these downsides:

  • it forces you to write your own copy constructors and assignment operators and you have to manage each variable individually, if you want to keep the semantic of copying.
  • the syntax of the code become very cumbersome, for example you will have std::vector<std::unique_ptr<MyClass>> instead of the much more simple std::vector<MyPimplClass>.
  • the constness of the pointer is not propagated to the pointed object, unless you use std::experimental::propagate_const, which I cannot use.

So it came to my mind to propose to use the pImpl idiom for the classes being included as a pointer instead of using pointers everywhere. In this way I thought we can have the best of both worlds:

  • Faster compile times: pimpl reduces compilation dependencies
  • To write your copy constructor and your copy assignment operator you just do this:
  • The constness is propagated to the member object.

At this point I had a discussion with my coworkers, they are arguing that pImpl is that it is not better than using pointers everywhere because of the following:

  • It reduces compilation dependencies less than using pointers, because if you are using pImpl you have to recompile the classes that includes your pImpl class when you change your public interface: if you were using just a pointer instead of the pImpl class you won't need to recompile even when changing the header file.

Now I am a little confused. I think that our actual convention is not really better than pImpl but I am not able to argue why.

So I have some questions:

  • Is the pImpl idiom a good alternative in this scenario?
  • Are there other downsides of the pattern we are using, except the ones that I mentioned?

Edit: I am adding some examples to clarify the two approaces.

  • Approach with unique_ptr as member:
  • Approach with pImpl:

Main:

Moreover I want to be more precise when I say that the first approach we don't need to recompile, this is inaccurate. It is true that we need to recompile less files:

  • If we change B.h we need to recompile only A.cpp, B.cpp.
  • If we change Bp.h we need to recompile Ap.cpp, Bp.cpp and main.cpp