使用 Qt 的元对象系统获取对象实例类名
Posted
技术标签:
【中文标题】使用 Qt 的元对象系统获取对象实例类名【英文标题】:Get object instance class name with Qt's meta-object system 【发布时间】:2020-11-05 13:56:11 【问题描述】:我有 3 个课程:
class Being : public QObject
Q_OBJECT
public:
explicit Being(QObject *parent = nullptr);
;
class Animal : public Being
Q_OBJECT
public:
explicit Animal(QObject *parent = nullptr);
;
class Dog : public Animal
Q_OBJECT
public:
explicit Dog(QObject *parent = nullptr);
;
Being的实现如下:
Being::Being(QObject *parent) : QObject(parent)
qDebug() << staticMetaObject.className();
我有以下代码:
Being *pBeing = new Being();
Being *pAnimal = new Animal();
Being *pDog = new Dog();
问题是:有没有办法实现Being的构造函数,这样我就可以访问指向我的Being基类的实际实例,这样上面代码的日志就会是:
Being
Animal
Dog
?
编辑:
我的意图是我希望能够在 Being 基类中处理 Animal.txt
、Being.txt
和 Doc.txt
。而且我需要知道,根据实例的类型,我是否需要解析Animal.txt
、Being.txt
或Doc.txt
以获取更多信息。
Qt 支持这个吗?有没有一种机制我可以使用 C++/Qt 来实现这一点?如果没有,是否有任何优雅的折衷解决方案?
【问题讨论】:
在 Being::Being 构造函数中你绝对需要这个吗?一旦构造了对象,您就可以引用元对象,但这在那时是不可能的(封闭对象尚未完全构造) 不一定在构造函数中,但我需要一种机制来知道,在我的 Being 类中,实例的类型为Being
、Animal
或 Dog
...
如果这是为了调试,那就是metaObject->className()
。如果您打算在类名上调度,请改用多态性。
不,这不仅仅是为了调试,请参阅我的编辑。我的自动机制会根据所使用的实例类型收集更多信息。
【参考方案1】:
在Being
的构造函数中是不可能的,因为尚未构造封闭对象,因此有关它的元数据不可用。但是,您可以编写应该在对象构造之后调用的 initialize
方法,例如带打印功能:
class Being : public QObject
Q_OBJECT
public:
explicit Being(QObject *parent = nullptr) qDebug() << this->metaObject()->className(); // this will always print "Being"
void initialize() qDebug() << this->metaObject()->className(); // this will print the actual class name
;
class Animal : public Being
Q_OBJECT
public:
explicit Animal(QObject *parent = nullptr) initialize(); // you can already use this method in the constructor
;
TEST(xxx, yyy)
Being* being = new Being();
Being* animal = new Animal();
being->initialize();
animal->initialize(); // or you can call it later
如果initialize
方法不是很好的解决方案,您可以随时通过Being
构造函数:explicit Being(QString name, QObject* parent = nullptr;
然后explicit Animal(QObject *parent = nullptr): Being("Animal")
破解它,但我认为它不太优雅。
【讨论】:
【参考方案2】:我的意图是我希望能够拥有将在 Being 基类中处理的 Animal.txt、Being.txt 和 Doc.txt。而且我需要知道,根据实例的类型,我是否需要解析 Animal.txt、Being.txt 或 Doc.txt 以获取更多信息。
永远不要让基类知道它的子类。永远。
无论它看起来多么诱人,都不要这样做(即使你知道怎么做)。
一个类可能有数百个子类。以QObject
为例。 QObject
是否应该(或者可能)知道您对 QMainWindow
的重新实现?
所以,无论做出这个设计决定的原因是什么,改变它!
可能的解决方案
如果文本文件的处理算法相同,无论子类如何,创建一个基类方法进行处理,并从子类中调用。
如果算法依赖于子类,将方法抽象化,即virtual
,不带实现(=0
),让实现到子类。
【讨论】:
以上是关于使用 Qt 的元对象系统获取对象实例类名的主要内容,如果未能解决你的问题,请参考以下文章