【问题标题】:Qt signal-slot duplication code avoidanceQt 信号槽重复代码避免
【发布时间】:2019-08-30 15:51:23
【问题描述】:

我想在不同的类之间共享信号和可能的插槽实现,但似乎 Qt 不允许这样做。

基本上我想要类似的东西:

class CommonSignals
  {
  signals:
  void mysignal();
  };

class A : 
    public QObject, 
    public CommonSignals
  {
    Q_OBJECT
  public:
    void doSomething()
      {
      emit mysignal();
      }
  };


class B : 
    public QObject, 
    public CommonSignals
  {
    Q_OBJECT

  public:

    B()
      {
      connect(&a, &A::mysignal, this, &B::mysignal);
      }

    A a;
  };

因此,当由于某种原因 A 发出信号时,B 也发出相同的信号。这样可以避免无用的代码复制并提高可维护性。

有什么想法吗?

PS 我也尝试过使用虚拟继承,但我遇到了经典的 qmake 问题

【问题讨论】:

  • 你有一个错字:connect(&a, &A::mysignal, this, &B::mysignal); 会修正你的错误。
  • 我已经编辑了问题,相信我不是那个问题:)
  • CommonSignals 不继承自 QObject,因此不能有与之关联的信号。您没有看到来自moc 的任何错误或警告消息吗?
  • @Jarod42 你可以将一个信号连接到另一个信号,这很好。
  • @G.M.使用多重继承,只允许一个基类是QObject。所以CommonSignals 不可能是一个。这意味着它不能使用信号。

标签: c++ qt inheritance signals-slots qobject


【解决方案1】:

你不能这样做。 QObject 不能与多个 QObject 基的多重继承一起使用。只有第一个继承的类可以是QObject。见:

https://doc.qt.io/qt-5/moc.html#multiple-inheritance-requires-qobject-to-be-first

由于您需要将两个基类都设为 QObjectCommonSignals 提供信号,因此它必须是 QObject),所以您很不走运。您唯一的选择是使用普通的旧宏:

#define COMMON_SIGNALS \
    void signal1(); \
    void signal2();

class A: public QObject
{
    Q_OBJECT

public:
    // ...

signals:
    COMMON_SIGNALS
};

class B: public QObject
{
    Q_OBJECT

public:
    // ...

signals:
    COMMON_SIGNALS
};

这一切的核心问题是 Qt 使用 moc 为信号和插槽生成底层代码。但是,moc 只是一个简单的预处理器,不能理解大部分 C++。

您可以使用 Verdigris 来摆脱 moc:

https://github.com/woboq/verdigris

例如,这允许您对 QObject 类进行模板化。我自己没有尝试过,因此不知道它是否真的允许多重继承。可能值得研究。

【讨论】:

  • 感谢您的反馈。我正在寻找一些解决方法,因为我不想使用宏,谁知道,也许有一些技巧 ehhe
  • 以某种方式使用 CRTP 怎么样?
  • @Saturnu 问题是 moc。它不理解模板。事实上,它并不了解大部分 C++。它只是在头文件中寻找一些简单的东西。你可以尝试使用它,它完全摆脱了 moc:github.com/woboq/verdigris
  • 是的,我听说了 Verdigris,谢谢。也许我将来会尝试,但我仍然有兴趣找到解决这个问题的方法。在某些情况下,我设法让模板和 Qt 一起工作;)
【解决方案2】:

为什么不将QObject 的继承从派生类AB 移到CommonSignals...

class CommonSignals: public QObject {
  Q_OBJECT;
signals:
  void mysignal();
};

class A: public CommonSignals {
  Q_OBJECT;
public:
  void doSomething ()
    {
      emit mysignal();
    }
};

class B: public CommonSignals {
  Q_OBJECT;
public:
  B ()
    {
      connect(&a, &A::mysignal, this, &B::mysignal);
    }
  A a;
};

这不适合你吗?

【讨论】:

  • 这将不允许您创建提供公共信号的 QLineEdit(或任何其他非直接派生自 QObjectQObject 类)。我认为这就是 OP 的想法。
  • 感谢您的反馈。不,我猜这个解决方案不好。实际上的目标是让 B 扩展其他类,例如CommonSignals2、CommonSignals3 等。如@NikosC。我认为这不适用于所有情况。
  • 好的。我想我误解了这个问题。
猜你喜欢
  • 1970-01-01
  • 2011-09-06
  • 2014-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多