不透明指针 (pimpl) 以及信号和槽

Opaque Pointer (pimpl) and signals and slots

我越来越喜欢 Pimpl idiom(指向真实 class 实现的私有不透明指针)。但是还有一个问题困扰着我。

这个 idiom\design 模式如何处理 public class 中的信号(比如 boost 或 qt 信号)?

class my_class : public QObject 
{
Q_OBJECT
public:
   void monitorstuff();
signal:
   void needupdate();
private:
    class impl; unique_ptr<impl> pimpl; // opaque type here
};


class my_class::impl {  
    void reallymonitorstuff();
};

my_class::impl::reallymonitorstuff()
{
  ...
  //update required here
  ...
}

void my_class::monitorstuff()
{
  pimpl->reallymonitorstuff();
}

Do I replicate all signals in the pimpl, connect with signals of the outer class? A bit annoying to have twice as much signals as what is publicly available, also annoying when I need to swap instances.

不,你不需要那样做。

Do I pass the public instance as parameter to the private instance which calls directly the public signals

那也没有必要。

Another design mechanism in conjuction I didn't heard of?

那也没有必要。

假设 my_class::monitorstuff 应该发出信号,我想你只需要:

void my_class::monitorstuff()
{
   pimpl->reallymonitorstuff();
   emit <<Details of signal>>;
}

pimpl不需要关心信号或槽。

总的来说,我真的看不出问题所在。 public class 应该将所有调用转发给 impl,包括连接插槽的调用。 impl 包含信号,而不是 public class。例如这里使用 Boost.Signals2:

#include <memory>
#include <boost/signals2.hpp>
#include <iostream>

using signal_type = boost::signals2::signal<void()>;
using slot_type = signal_type::slot_type;

class my_class {
public:
   my_class(); 
   void monitorstuff();
   void connect(const slot_type& slot);
private:
   struct impl; std::unique_ptr<impl> pimpl;
};

struct my_class::impl {
  signal_type signal;
  void reallymonitorstuff();
  void connect(const slot_type& slot){ signal.connect(slot); }
};

void
my_class::impl::reallymonitorstuff() {
  //...
  signal();
  //...
}

void my_class::monitorstuff() {
  pimpl->reallymonitorstuff();
}

void my_class::connect(const slot_type& slot) {
  pimpl->connect(slot);
}

my_class::my_class() : pimpl(std::make_unique<my_class::impl>()){}

int main() {
    my_class mc;
    auto slot = []{ std::cout << "Notified!\n"; };
    mc.connect(slot);
    mc.monitorstuff();
}

Live demo.

我想知道你的问题是否更具体到 Qt。