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

时间:2015-09-08 16:19:02

标签: c++ signals-slots pimpl-idiom

我越来越多地进入Pimpl idiom(指向实际类实现的私有不透明指针)。但我仍然有一个困扰我的问题。

这个成语\设计模式如何处理公共类中的信号(如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();
}
  • 我是否复制pimpl中的所有信号,连接外部类的信号?有点烦人的信号是公共可用信号的两倍,当我需要交换实例时也很烦人。
  • 我是否将公共实例作为参数传递给直接调用公共信号的私有实例
  • 我没有听说过另一种设计机制吗?

2 个答案:

答案 0 :(得分:1)

  

我是否复制了pimpl中的所有信号,并连接外部类的信号?有点烦人的信号是公共可用信号的两倍,当我需要交换实例时也很烦人。

不,你不需要这样做。

  

我是否将公共实例作为参数传递给直接调用公共信号的私有实例

这也没必要。

  

我没有听说过另一种设计机制?

这也没必要。

假设my_class::monitorstuff应该发出信号,我认为您需要的只是:

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

pimpl无需关注信号或插槽。

答案 1 :(得分:0)

总的来说,我真的没有看到这个问题。公共类应该转发所有对impl的调用,包括连接插槽的调用。 impl包含信号,而不是公共类。例如,使用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。