簡體   English   中英

如何為 QObject class 創建接口

[英]How create Interface for QObject class

我想用信號/槽系統為QObject class 創建一個接口。

下面的代碼有效但有一個缺點:接口繼承QObject並且沒有Q_OBJECT宏。

我想制作一個純虛擬接口,所以InterfaceClass不應該有構造函數。 但是在RealisationClass中,我無法調用QObject (錯誤:類型“QObject”不是“RealisationClass”的直接基礎)或InterfaceClass (它沒有構造函數InterfaceClass(QObject* parent) )構造函數。 此外,我無法在InterfaceClass中添加Q_OBJECT宏(錯誤:未定義對 InterfaceClass 的“vtable”的引用)

那么,我應該如何更改類以在RealisationClass中添加QObject()構造函數並將Q_OBJECT宏(或刪除QObject繼承)添加到 InterfaceClass。

接口類.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

實現類.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";};
};

主.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();
}

編輯

Q_OBJECT 宏問題還有另一個原因:我沒有將 InterfaceClass.h 作為目標添加到 Cmake 的 AUTOMOC(qmake (moc) 沒有處理這個文件)。

使用具有QObject層次結構的接口是一個真正的痛苦。 您通常希望您的接口具有QObject的某些功能(即信號/槽、銷毀信號、與 Qt API 集成),但它是一個輕量級的接口定義。 除非重構IQObject以便存在在整個 Qt 代碼庫中使用的 IQObject,否則您無法獲得完美的解決方案。 我推薦的是簡單地將所有構造函數調用轉發給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

通過using QObject::QObject行, InterfaceClass現在具有與QObject具有相同聲明的構造函數。 他們所做的就是將調用轉發給QObject 有了它,您現在可以在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";};
};

這有兩個主要缺點:

  1. 由於構造函數,您的界面不再是真正的界面。
  2. 您的派生類不能從以這種方式設計的多個接口繼承(菱形繼承)。

我仍然需要嘗試使用虛擬 inheritance ( class InterfaceClass: public virtual QObject ) 看看是否可以在不引入其他問題的情況下解決#2。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM