简体   繁体   English

如何为 QObject class 创建接口

[英]How create Interface for QObject class

I want to create an interface for QObject class with signal/slot system.我想用信号/槽系统为QObject class 创建一个接口。

The code below works but has a disadvantage: Interface inherits QObject and has no Q_OBJECT macro.下面的代码有效但有一个缺点:接口继承QObject并且没有Q_OBJECT宏。

I want to make a pure virtual interface, so InterfaceClass shouldn't have a constructor.我想制作一个纯虚拟接口,所以InterfaceClass不应该有构造函数。 But in RealisationClass I cannot call QObject (error: type 'QObject' is not a direct base of 'RealisationClass') nor InterfaceClass (It hasn't constructor InterfaceClass(QObject* parent) ) constructors.但是在RealisationClass中,我无法调用QObject (错误:类型“QObject”不是“RealisationClass”的直接基础)或InterfaceClass (它没有构造函数InterfaceClass(QObject* parent) )构造函数。 Moreover I cannot add Q_OBJECT macro in InterfaceClass (error: undefined reference to 'vtable' for InterfaceClass')此外,我无法在InterfaceClass中添加Q_OBJECT宏(错误:未定义对 InterfaceClass 的“vtable”的引用)

So, how should I change classes to add QObject() constructor in RealisationClass and add Q_OBJECT macro (or remove QObject inheritance) to InterfaceClass.那么,我应该如何更改类以在RealisationClass中添加QObject()构造函数并将Q_OBJECT宏(或删除QObject继承)添加到 InterfaceClass。

IntefaceClass.h:接口类.h:

#ifndef INTERFACE_CLASS_H
#define INTERFACE_CLASS_H
#include <QObject>

class InterfaceClass : public QObject {
    Q_OBJECT
 public:
  virtual ~InterfaceClass(){};
  virtual void foo() = 0;
};
Q_DECLARE_INTERFACE(InterfaceClass, "Interface")
#endif // INTERFACE_CLASS_H

RealisationClass.h:实现类.h:

#include <QObject>
#include <QDebug>

#include "InterfaceClass.h"

class RealisationClass : public InterfaceClass {
  Q_OBJECT
  Q_INTERFACES(InterfaceClass)
 public:
    explicit RealisationClass(QObject* parent = nullptr){};
    void foo() override {qDebug() << "Hello, world";};
};

main.cpp:主.cpp:

#include <QCoreApplication>

#include "RealisationClass.h"
#include "InterfaceClass.h"
#include <QObject>
#include <QTimer>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTimer everySecondTimer;
    everySecondTimer.setInterval(1000);
    QScopedPointer<InterfaceClass> interfacePointer(new RealisationClass);
    QObject::connect(&everySecondTimer, &QTimer::timeout, interfacePointer.get(), &InterfaceClass::foo);
    everySecondTimer.start();
    return a.exec();
}

Edit编辑

Q_OBJECT macro problem has another reason: I don't add InterfaceClass.h as target to Cmake's AUTOMOC (qmake (moc) didn't handle this file). Q_OBJECT 宏问题还有另一个原因:我没有将 InterfaceClass.h 作为目标添加到 Cmake 的 AUTOMOC(qmake (moc) 没有处理这个文件)。

Using interfaces with QObject hierarchies is a real pain.使用具有QObject层次结构的接口是一个真正的痛苦。 You often want your interface to have some features of QObject (ie. signals/slots, destroyed signal, integrates with Qt APIs) but have it be a lightweight interface definition.您通常希望您的接口具有QObject的某些功能(即信号/槽、销毁信号、与 Qt API 集成),但它是一个轻量级的接口定义。 Unless Qt is refactored so that an IQObject exists that is used throughout the Qt code-base, you can't get a perfect solution.除非重构IQObject以便存在在整个 Qt 代码库中使用的 IQObject,否则您无法获得完美的解决方案。 What I recommend is to simply forward all constructor calls through to QObject :我推荐的是简单地将所有构造函数调用转发给QObject

#ifndef INTERFACE_CLASS_H
#define INTERFACE_CLASS_H
#include <QObject>

class InterfaceClass : public QObject {
    Q_OBJECT
 public:
  using QObject::QObject; // <<--------

  virtual ~InterfaceClass(){};
  virtual void foo() = 0;
};
Q_DECLARE_INTERFACE(InterfaceClass, "Interface")
#endif // INTERFACE_CLASS_H

With the using QObject::QObject line, InterfaceClass now has constructors with the same declarations as QObject .通过using QObject::QObject行, InterfaceClass现在具有与QObject具有相同声明的构造函数。 All they do is forward the call to QObject .他们所做的就是将调用转发给QObject With that, you can now do this in RealisationClass :有了它,您现在可以在RealisationClass中执行此操作:

#include <QObject>
#include <QDebug>

#include "InterfaceClass.h"

class RealisationClass : public InterfaceClass {
  Q_OBJECT
  Q_INTERFACES(InterfaceClass)
 public:
    explicit RealisationClass(QObject* parent = nullptr)
      : InterfaceClass(parent) // <<------
    {};
    void foo() override {qDebug() << "Hello, world";};
};

This has two major downsides:这有两个主要缺点:

  1. Your interface is no longer a true interface because of the constructors.由于构造函数,您的界面不再是真正的界面。
  2. Your derived classes cannot inherit from multiple interfaces designed this way (diamond inheritance).您的派生类不能从以这种方式设计的多个接口继承(菱形继承)。

I still need to play around with virtual inheritance ( class InterfaceClass: public virtual QObject ) to see if that can solve #2 without introducing other issues.我仍然需要尝试使用虚拟 inheritance ( class InterfaceClass: public virtual QObject ) 看看是否可以在不引入其他问题的情况下解决#2。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM