将 pimpl 参数传递给 pimpl 对象

Pass pimpl argument to a pimpl object

我有两个 class 实现了 PIMPL:State 和 StateMachine。

他们实施 Private::State 和 Private::State 机器。

Private::State机器有一个 "addState(Private::State &)" 方法。我想将 addState() 方法写入其 PIMPL class,以便

StateMachine machine;
State        state;

machine.addState(state);

如何将状态中的对象 Private::State 传递给 StateMachine 中的 Private::StateMachine?

StateMachine.h

#include <memory>

class State;
namespace Private {
  class StateMachine;
} // namespace Private

class StateMachine
{
public:
  StateMachine();
  ~StateMachine();

  // want to add this
  void addState(const State &state);

private:
  std::unique_ptr<Private::StateMachine> m_stateMachine;
};

State.h

#include <memory>

namespace Private {
class State;
} // namespace Private

namespace StateMachine {

class State
{
public:
  State();
  ~State();

private:

  std::unique_ptr<Private::State> m_state;
};

这个问题可能有无数个答案。

以下是一些可以指导您思考的问题:

  1. 复制一个State对象应该有什么效果?内部 Private::State 也应该被复制吗?
  2. 是否应该禁止复制(更喜欢移动)?在这种情况下,您需要转储用户定义的构造函数,允许编译器为您生成移动。
  3. 假设 (2),您的 Private::StateMachine 应该存储 unique_ptr<Private::State> 还是 unique_ptr<State>?这变得很棘手,因为如果你想在 pimpl 后面的状态和机器之间直接交互,你可能想要存储一个 unique_ptr<Private::State> 以避免在 ::State 接口中暴露私有操作。如果您想将 State 返回给用户代码,则必须重建 ::State 句柄。这可能会支持 ::State.
  4. 的非拥有版本
  5. 使用pimpl的目的是什么? StatePrivate::State 的句柄吗?拥有 'null handle' 的概念是否合理(例如作为移动的结果)? 2 个句柄是否应该在复制期间共享相同的状态(争论shared_ptr)?等等。

总之,有一个答案,但这完全取决于 StateMachine、State 的概要以及它们在用户代码中所需的交互。我建议您从这里开始 - 设计用例并观察它们对复制、移动、分配等的影响。这应该会引导您自然地实现。