首页 > 解决方案 > Qt 基类函数定义

问题描述

我正在使用 gcc 4.8.5 在使用 Qt5 的项目中构建模板库,目标是发送和接收不共享继承层次结构的类型。我想出的一种可能的解决方案是,基类可以简单地定义信号和插槽,而派生类可以提供实现,这很有效。现在,为了编译时优化和运行时性能,如果我在基类中有数百个这样的方法会发生什么?

我无法找到的另一个有效问题似乎是当两个派生类继承同一个对象时在编译期间会发生什么。以下面的例子为例:

class A{}

class B : A{}

class C : A{}

这种结构有编译时的好处吗?此外,Qt 不会为一个类创建 moc,除非它定义了一个信号或插槽,所以会有

class A {
    void slot_1();
    //...
    void slot_100();
}

停止编译,这是否有任何运行时开销?我知道 Qt 插槽下面只是一个函数,因此在内存中只创建了一个函数。此外,我知道派生类必须链接 moc_a.o 文件,但我不太确定链接器能够优化到什么程度。

注意:我知道这违反了 SRP 和 OCP,但上面列出了我最大的担忧和障碍。只要它们不是不必要的复杂且编译时友好,我愿意研究替代示例和解决方法。ISP 也出局了,我根本没有做那么多的多重继承。

标签: c++qtclassinheritancelinker

解决方案


这是一个 XY 问题:您正在询问解决方案,但您要解决的实际问题是什么?这些类代表什么?“发送和接收类型”是什么意思?至于不共享继承层次结构,有一些简单的方法:一个通用接口可以由一个通用实现的方法提供,如果你添加Q_GADGETQ_OBJECT到类中,你可以自省该方法——假设它们已经不是QObjects。如果你使用QObject,那么你可以通过编程方式调用方法QMetaObject::invokeMethod,或者通过QMetaMethod::invokeOnGadgeton类型,并且除了自身Q_GADGET之外确实不需要任何通用接口。QObject

例子:

#include <QtCore>

class Class1 {
  Q_GADGET
public:
  Q_INVOKABLE void foo() { qDebug() << "Class1::foo"; }
};

class Class2 : public QObject {
  Q_OBJECT
public:
  Q_SLOT void foo() { qDebug() << "Class2::foo"; }
};

class Class3 : public QObject {
  Q_OBJECT
public:
  Q_SLOT void bar() { qDebug() << "Class3::bar"; }
};

template <class C> QMetaMethod getMethod(const C& c, const char *signature) {
  auto const &mo = c.staticMetaObject;
  auto const nSignature = QMetaObject::normalizedSignature(signature);
  int index = mo.indexOfMethod(nSignature);
  if (index >= 0)
    return mo.method(index);
  return {};
}

int main() {
  Class1 c1;
  Class2 c2;
  Class3 c3;
  auto foo1 = getMethod(c1, "foo()");
  auto foo2 = getMethod(c2, "foo()");
  auto bar3 = getMethod(c3, "bar()");
  foo1.invokeOnGadget(&c1);
  foo2.invoke(&c2);
  bar3.invoke(&c3);  
}
#include "main.moc"

推荐阅读