【问题标题】:Get object instance class name with Qt's meta-object system使用 Qt 的元对象系统获取对象实例类名
【发布时间】: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.txtBeing.txtDoc.txt。而且我需要知道,根据实例的类型,我是否需要解析Animal.txtBeing.txtDoc.txt 以获取更多信息。

Qt 支持这个吗?有没有一种机制我可以使用 C++/Qt 来实现这一点?如果没有,是否有任何优雅的折衷解决方案?

【问题讨论】:

  • 在 Being::Being 构造函数中你绝对需要这个吗?一旦构造了对象,您就可以引用元对象,但这在那时是不可能的(封闭对象尚未完全构造)
  • 不一定在构造函数中,但我需要一种机制来知道,在我的 Being 类中,实例的类型为 BeingAnimalDog...
  • 如果这是为了调试,那就是metaObject-&gt;className()。如果您打算在类名上调度,请改用多态性。
  • 不,这不仅仅是为了调试,请参阅我的编辑。我的自动机制会根据所使用的实例类型收集更多信息。

标签: c++ qt qt5 qmetaobject qmetatype


【解决方案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),让实现到子类。

    【讨论】:

      猜你喜欢
      • 2011-05-13
      • 2011-01-30
      • 1970-01-01
      • 2015-08-19
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 2011-01-10
      相关资源
      最近更新 更多