C++ 使用Qt';获取对象实例类名;s元对象系统

C++ 使用Qt';获取对象实例类名;s元对象系统,c++,qt,qt5,qmetaobject,qmetatype,C++,Qt,Qt5,Qmetaobject,Qmetatype,我有三门课: 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_OBJ

我有三门课:

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);
};
BEIN的实施情况如下:

Being::Being(QObject *parent) : QObject(parent) {
    qDebug() << staticMetaObject.className();
}
问题是:有没有办法实现Being的构造函数,这样我就可以访问指向Being基类的实际实例,这样上面代码的日志就会是:

Being
Animal
Dog
?

编辑: 我的目的是希望能够在Being基类中处理
Animal.txt
Being.txt
Doc.txt
。根据实例的类型,我需要知道是否需要解析
Animal.txt
Being.txt
Doc.txt
,以获得更多信息


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

的构造函数中是不可能的,因为封闭对象尚未构造,因此有关它的元数据不可用。但是,您可以编写在对象构造后应调用的
初始化
方法,例如,使用打印功能:

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
}
类为:公共QObject{
Q_对象
公众:
显式存在(QObject*parent=nullptr){qDebug()元对象()->className();}//这将始终打印“存在”
void initialize(){qDebug()元对象()->className();}//这将打印实际的类名
};
动物类别:公共存在{
Q_对象
公众:
显式Animal(QObject*parent=nullptr){initialize();}//您已经可以在构造函数中使用此方法
};
测试(xxx,yyy)
{
Being*Being=新的Being();
成为*动物=新动物();
正在->初始化();
animal->initialize();//或者您可以稍后调用它
}
如果
initialize
方法不是一个好的解决方案,你可以通过
Being
构造函数:
explicit Being(QString名称,QObject*parent=nullptr;
然后
explicit Animal(QObject*parent=nullptr):Being(“Animal”){}
,但我认为它不够优雅

我的目的是希望能够在Being基类中处理Animal.txt、Being.txt和Doc.txt。我需要知道,根据实例的类型,我是否需要解析Animal.txt、Being.txt或Doc.txt以获得更多信息

永远不要让基类知道它的子类

无论它看起来多么诱人,都不要去做(即使你知道怎么做)

一个类可能有数百个子类。例如
QObject
QObject
(或者可能)是否应该知道重新实现
QMainWindow

因此,无论这个设计决策的原因是什么,改变它!

可能的解决方案 如果文本文件的处理算法相同,不管子类是什么,创建一个基类方法来进行处理,并从子类调用它


如果算法依赖于子类,则将方法抽象化,即
虚拟
且不进行实现(
=0
),并将实现转移到子类。

在Being::Being构造函数中是否绝对需要此功能?一旦构造了对象,您可以引用元对象,但此时不可能(封闭对象尚未完全构造)不一定在构造函数中,但我需要一种机制来知道,在我的Being类中,实例的类型是
Being
Animal
Dog
…如果这是为了调试,那就是
元对象->类名()
。如果您计划对类名进行分派,请改用多态性。不,多态性不仅仅用于调试,请参阅我的编辑。我知道这是一种自动机制,可以根据使用的实例类型收集更多信息。
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
}