4

我有一个由两个子类继承的基类。所有三个类都使用 qDebug() 进行一些调试打印,并使用 Q_FUNC_INFO 来识别打印源。问题是从基类打印时,Q_FUNC_INFO 包含基类的名称,因此无法知道实例代表两个子类中的哪一个。

到目前为止,我提出的最佳解决方案是在基类中使用 QString 变量而不是 Q_FUNC_INFO 并在实例化时为其提供正确的名称。

还有其他更可取的解决方案吗?

4

1 回答 1

4

还有其他更可取的解决方案吗?

一般来说,不,那很好。在这种情况下,如果可能,您需要将 Q_FUNC_INFO 放入子类中。如果没有,那你就不走运了,但是……请继续阅读。

Qt 内部也使用显式字符串而不是 Q_FUNC_INFO,我相信部分是因为这个原因。

对于 QObjects,您可以使用元对象编译器进行一些内省以动态获取真实名称,即:

const char * QMetaObject::className() const

返回类名。

const QMetaObject * QObject::metaObject() const [虚拟]

返回指向此对象的元对象的指针。

元对象包含有关继承 QObject 的类的信息,例如类名、超类名、属性、信号和槽。每个包含 Q_OBJECT 宏的 QObject 子类都会有一个元对象。

信号/槽连接机制和属性系统需要元对象信息。inherits() 函数也使用元对象。

如果您没有指向实际对象实例的指针,但仍想访问类的元对象,则可以使用 staticMetaObject。

在处理构造函数时,您还可以查看这一点,因为您的评论似乎表明了这一点:

QMetaMethod QMetaObject::constructor(int index) const

返回具有给定索引的构造函数的元数据。

主文件

#include <QObject>
#include <QDebug>

class Foo : public QObject
{
    Q_OBJECT
    public:
        virtual void baz() {  qDebug() << "Class name:" << metaObject()->className(); }
};

class Bar : public Foo
{
    Q_OBJECT
};

#include "main.moc"

int main()
{
    Bar bar;
    bar.baz();
    return 0;
}

输出

moc main.cpp -o main.moc && g++ -Wall -I/usr/include/qt -I/usr/include/ -I/usr/include/qt/QtCore -lQt5Core -fPIC main.cpp && ./a.out

Class name: Bar

注意:如果你想让这个机制在构造函数中工作,简单的答案是你不能。那里没有什么能真正帮助你。这是因为在 C++ 中继承是如何处理的。首先,基类被构建,在那个阶段,子类尚未完全构建(严格来说,甚至不是基类),因此如果不明确确保基类的附加参数,您将无法真正获得有关它的更多信息构造函数。但是,你会为这个简单的事情得到一个臃肿的 API。在这种情况下,我建议将打印内容放入子类而不是基类中。

于 2013-12-19T09:07:35.217 回答