如何定义一个类,使其继承自 QObject 以及在 QObject 派生类中?

问题描述 投票:0回答:1

class A
中,我定义了一个
class B
。我想隐藏
class B
的实现。
class B
继承自
QObject

// a.h
class A : public QObject
{
    Q_OBJECT
public:
    explicit A(QObjcet* parent=nullptr);
private:
    class B;
    QSharedPointer<B> m_impl;
};

//a.cpp
class A::B : public QObject
{
    Q_OBJECT
public:
    ...
};

A::A(QObject* parent) : 
    QObject(parent),
    m_impl(QSharedPointer<B>(new B()))
{
}

但是有错误:

对“A::B 的 vtable”的未定义引用
对“A::B::staticMetaObject”的未定义引用

造成这些问题的原因是什么,如何解决?

c++ qt inheritance qobject
1个回答
1
投票

对于要编译的

QObject
派生类,您需要一个包含
Q_OBJECT
宏定义的额外单元,该单元由元对象编译器(moc)实用程序根据声明类的标头内容生成。

Qt 不支持嵌套类或从多个

QObject
继承的类,并且可能工作也可能不工作。元对象编译器也不适用于 .cpp 文件,因为它解析代码的能力有限。默认情况下,Qt 工具链不会在 .cpp 文件上运行
moc

您可以创建一个额外的编译步骤来运行

moc
,但这是一个肮脏且奇怪的解决方案,如果您的类派生于
QObject
,则最好有一个单独的“私有”标头,隐藏在没有外来的文件夹中单位会向上看。

//impl/a_private.h
class A::B : public QObject
{
    Q_OBJECT
public:
    ...
};

 //a.cpp
 #include "a.h"
 #include "impl/a_private.h"
 ...

这看起来 B 应该是 A 中使用的私有(“桥接”)类:

class B;
QSharedPointer<B> m_impl;

在这种情况下,您必须使用 Qt 的 PIMPL 又名 Cheshire cat 模式,它是 Bridge 模式的变体。

如何使用Qt的PIMPL惯用法?

TLDR:

A::B
将成为全局命名空间中的
class APrivate

© www.soinside.com 2019 - 2024. All rights reserved.