在
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”的未定义引用
造成这些问题的原因是什么,如何解决?
对于要编译的
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 模式的变体。
TLDR:
A::B
将成为全局命名空间中的class APrivate